Initial data commit
This commit is contained in:
parent
72d218235f
commit
f23f22d71c
199087 changed files with 3378941 additions and 0 deletions
3
Task/CUSIP/00-META.yaml
Normal file
3
Task/CUSIP/00-META.yaml
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
from: http://rosettacode.org/wiki/CUSIP
|
||||
note: Checksums
|
||||
49
Task/CUSIP/00-TASK.txt
Normal file
49
Task/CUSIP/00-TASK.txt
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
<br/>
|
||||
|
||||
A '''CUSIP''' is a nine-character alphanumeric code that identifies a North American financial security for the purposes of facilitating clearing and settlement of trades. The CUSIP was adopted as an American National Standard under Accredited Standards X9.6.
|
||||
|
||||
|
||||
;Task:
|
||||
Ensure the last digit (i.e., the ''check digit'') of the '''CUSIP''' code (the 1<sup>st</sup> column) is correct, against the following:
|
||||
* 037833100 Apple Incorporated
|
||||
* 17275R102 Cisco Systems
|
||||
* 38259P508 Google Incorporated
|
||||
* 594918104 Microsoft Corporation
|
||||
* 68389X106 Oracle Corporation (''incorrect'')
|
||||
* 68389X105 Oracle Corporation
|
||||
|
||||
|
||||
;Example pseudo-code below.
|
||||
<syntaxhighlight lang=text>algorithm Cusip-Check-Digit(cusip) is
|
||||
Input: an 8-character CUSIP
|
||||
|
||||
sum := 0
|
||||
for 1 ≤ i ≤ 8 do
|
||||
c := the ith character of cusip
|
||||
if c is a digit then
|
||||
v := numeric value of the digit c
|
||||
else if c is a letter then
|
||||
p := ordinal position of c in the alphabet (A=1, B=2...)
|
||||
v := p + 9
|
||||
else if c = "*" then
|
||||
v := 36
|
||||
else if c = "@" then
|
||||
v := 37
|
||||
else if' c = "#" then
|
||||
v := 38
|
||||
end if
|
||||
if i is even then
|
||||
v := v × 2
|
||||
end if
|
||||
|
||||
sum := sum + int ( v div 10 ) + v mod 10
|
||||
repeat
|
||||
|
||||
return (10 - (sum mod 10)) mod 10
|
||||
end function</syntaxhighlight>
|
||||
|
||||
;See related tasks:
|
||||
* [[SEDOLs|SEDOL]]
|
||||
* [[Validate_International_Securities_Identification_Number|ISIN]]
|
||||
<br>
|
||||
|
||||
36
Task/CUSIP/11l/cusip.11l
Normal file
36
Task/CUSIP/11l/cusip.11l
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
F cusip_check(=cusip)
|
||||
I cusip.len != 9
|
||||
X ValueError(‘CUSIP must be 9 characters’)
|
||||
|
||||
cusip = cusip.uppercase()
|
||||
V total = 0
|
||||
L(i) 8
|
||||
V v = 0
|
||||
V c = cusip[i]
|
||||
I c.is_digit()
|
||||
v = Int(c)
|
||||
E I c.is_alpha()
|
||||
V p = c.code - ‘A’.code + 1
|
||||
v = p + 9
|
||||
E I c == ‘*’
|
||||
v = 36
|
||||
E I c == ‘@’
|
||||
v = 37
|
||||
E I c == ‘#’
|
||||
v = 38
|
||||
|
||||
I i % 2 != 0
|
||||
v *= 2
|
||||
|
||||
total += v I/ 10 + v % 10
|
||||
V check = (10 - (total % 10)) % 10
|
||||
R String(check) == cusip.last
|
||||
|
||||
V codes = [‘037833100’,
|
||||
‘17275R102’,
|
||||
‘38259P508’,
|
||||
‘594918104’,
|
||||
‘68389X106’,
|
||||
‘68389X105’]
|
||||
L(code) codes
|
||||
print(code‘: ’(I cusip_check(code) {‘valid’} E ‘invalid’))
|
||||
81
Task/CUSIP/360-Assembly/cusip.360
Normal file
81
Task/CUSIP/360-Assembly/cusip.360
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
* CUSIP 07/06/2018
|
||||
CUSIP CSECT
|
||||
USING CUSIP,R13 base register
|
||||
B 72(R15) skip savearea
|
||||
DC 17F'0' savearea
|
||||
SAVE (14,12) save previous context
|
||||
ST R13,4(R15) link backward
|
||||
ST R15,8(R13) link forward
|
||||
LR R13,R15 set addressability
|
||||
LA R6,1 i=1
|
||||
DO WHILE=(C,R6,LE,=F'6') do i=1 to 6
|
||||
LR R1,R6 i
|
||||
MH R1,=H'9' *9
|
||||
LA R4,T-9(R1) @t(i)
|
||||
MVC X,0(R4) x=t(i)
|
||||
SR R10,R10 w=0
|
||||
LA R7,1 j=1
|
||||
DO WHILE=(C,R7,LE,=F'8') do j=1 to 8
|
||||
LA R14,X-1 x
|
||||
AR R14,R7 j
|
||||
MVC Y(1),0(R14) y=substr(x,j,1)
|
||||
LA R9,L'XX z=length(xx)
|
||||
LA R8,1 k=1
|
||||
DO WHILE=(C,R8,LE,=A(L'XX)) do k=1 to length(xx)
|
||||
LA R4,XX-1 xx
|
||||
AR R4,R8 k
|
||||
MVC C(1),0(R4) c=substr(xx,k,1)
|
||||
IF CLC,Y(1),EQ,C THEN if y=c then
|
||||
LR R9,R8 k
|
||||
BCTR R9,0 z=k-1
|
||||
ENDIF , endif
|
||||
LA R8,1(R8) k++
|
||||
ENDDO , enddo k
|
||||
LR R4,R7 j
|
||||
LA R1,2 2
|
||||
SRDA R4,32 ~
|
||||
DR R4,R1 j/2=0
|
||||
IF LTR,R4,Z,R4 THEN if j//2=0 then
|
||||
AR R9,R9 z=z+z
|
||||
ENDIF , endif
|
||||
LR R4,R9 z
|
||||
LA R1,10 10
|
||||
SRDA R4,32 ~
|
||||
DR R4,R1 r4=z//10 ; r5=z/10
|
||||
AR R10,R5 w+z/10
|
||||
AR R10,R4 w=w+z/10+z//10
|
||||
LA R7,1(R7) j++
|
||||
ENDDO , enddo j
|
||||
LR R4,R10 w
|
||||
LA R1,10 10
|
||||
SRDA R4,32 ~
|
||||
DR R4,R1 w/10
|
||||
LA R2,10 10
|
||||
SR R2,R4 10-w//10
|
||||
SRDA R2,32 ~
|
||||
DR R2,R1 /10
|
||||
STC R2,U u=(10-w//10)//10
|
||||
OI U,X'F0' bin to char
|
||||
IF CLC,U,EQ,X+8 THEN if u=substr(x,9,1) then
|
||||
MVC OK,=CL3' ' ok=' '
|
||||
ELSE , else
|
||||
MVC OK,=C'n''t' ok='n''t'
|
||||
ENDIF , endif
|
||||
MVC PG+6(9),X output x
|
||||
MVC PG+18(3),OK output ok
|
||||
XPRNT PG,L'PG print
|
||||
LA R6,1(R6) i++
|
||||
ENDDO , enddo i
|
||||
L R13,4(0,R13) restore previous savearea pointer
|
||||
RETURN (14,12),RC=0 restore registers from calling sav
|
||||
XX DC CL39'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ*@#'
|
||||
U DS CL1
|
||||
Y DS CL1
|
||||
C DS CL1
|
||||
T DC CL9'037833100',CL9'17275R102',CL9'38259P508'
|
||||
DC CL9'594918104',CL9'68389X106',CL9'68389X105'
|
||||
X DS CL9
|
||||
OK DS CL3
|
||||
PG DC CL80'CUSIP ......... is... valid'
|
||||
YREGS
|
||||
END CUSIP
|
||||
49
Task/CUSIP/ALGOL-68/cusip.alg
Normal file
49
Task/CUSIP/ALGOL-68/cusip.alg
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
BEGIN
|
||||
# returns TRUE if cusip is a valid CUSIP code #
|
||||
OP ISCUSIP = ( STRING cusip )BOOL:
|
||||
IF ( UPB cusip - LWB cusip ) /= 8
|
||||
THEN
|
||||
# code is wrong length #
|
||||
FALSE
|
||||
ELSE
|
||||
# string is 9 characters long - check it is valid #
|
||||
STRING cusip digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ*@#"[ AT 0 ];
|
||||
INT check digit := 0;
|
||||
IF NOT char in string( cusip[ UPB cusip ], check digit, cusip digits )
|
||||
THEN
|
||||
# invalid check digit #
|
||||
FALSE
|
||||
ELSE
|
||||
# OK so far compare the calculated check sum to the supplied one #
|
||||
INT sum := 0;
|
||||
INT c pos := LWB cusip - 1;
|
||||
FOR i TO 8 DO
|
||||
INT digit := 0;
|
||||
IF NOT char in string( cusip[ i + c pos ], digit, cusip digits )
|
||||
THEN
|
||||
# invalid digit #
|
||||
digit := -999
|
||||
FI;
|
||||
IF NOT ODD i
|
||||
THEN
|
||||
# even digit #
|
||||
digit *:= 2
|
||||
FI;
|
||||
sum +:= ( digit OVER 10 ) + ( digit MOD 10 )
|
||||
OD;
|
||||
( 10 - ( sum MOD 10 ) ) MOD 10 = check digit
|
||||
FI
|
||||
FI ; # ISCUSIP #
|
||||
|
||||
# task test cases #
|
||||
|
||||
PROC test cusip = ( STRING cusip )VOID:
|
||||
print( ( cusip, IF ISCUSIP cusip THEN " valid" ELSE " invalid" FI, newline ) );
|
||||
|
||||
test cusip( "037833100" );
|
||||
test cusip( "17275R102" );
|
||||
test cusip( "38259P508" );
|
||||
test cusip( "594918104" );
|
||||
test cusip( "68389X106" );
|
||||
test cusip( "68389X105" )
|
||||
END
|
||||
35
Task/CUSIP/ALGOL-W/cusip.alg
Normal file
35
Task/CUSIP/ALGOL-W/cusip.alg
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
begin % returns true if cusip is a valid CUSIP code %
|
||||
logical procedure isCusip ( string(9) value cusip ) ;
|
||||
begin
|
||||
% returns the base 39 digit corresponding to a character of a CUSIP code %
|
||||
integer procedure cusipDigit( string(1) value cChar ) ;
|
||||
if cChar >= "0" and cChar <= "9" then ( decode( cChar ) - decode( "0" ) )
|
||||
else if cChar >= "A" and cChar <= "Z" then ( decode( cChar ) - decode( "A" ) ) + 10
|
||||
else if cChar = "*" then 36
|
||||
else if cChar = "@" then 37
|
||||
else if cChar = "#" then 38
|
||||
else % invalid digit % -999 ;
|
||||
|
||||
integer checkDigit, sum;
|
||||
checkDigit := cusipDigit( cusip( 8 // 1 ) );
|
||||
for cPos := 1 until 8 do begin
|
||||
integer digit;
|
||||
digit := cusipDigit( cusip( ( cPos - 1 ) // 1 ) );
|
||||
if not odd( cPos ) then digit := digit * 2;
|
||||
sum := sum + ( digit div 10 ) + ( digit rem 10 )
|
||||
end for_cPos ;
|
||||
( ( 10 - ( sum rem 10 ) ) rem 10 ) = checkDigit
|
||||
end isCusip ;
|
||||
|
||||
begin % task test cases %
|
||||
procedure testCusip ( string(9) value cusip ) ;
|
||||
write( s_w := 0, cusip, if isCusip( cusip ) then " valid" else " invalid" );
|
||||
|
||||
testCusip( "037833100" );
|
||||
testCusip( "17275R102" );
|
||||
testCusip( "38259P508" );
|
||||
testCusip( "594918104" );
|
||||
testCusip( "68389X106" );
|
||||
testCusip( "68389X105" )
|
||||
end testCases
|
||||
end.
|
||||
41
Task/CUSIP/AWK/cusip.awk
Normal file
41
Task/CUSIP/AWK/cusip.awk
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# syntax: GAWK -f CUSIP.AWK
|
||||
BEGIN {
|
||||
n = split("037833100,17275R102,38259P508,594918104,68389X106,68389X105",arr,",")
|
||||
for (i=1; i<=n; i++) {
|
||||
printf("%9s %s\n",arr[i],cusip(arr[i]))
|
||||
}
|
||||
exit(0)
|
||||
}
|
||||
function cusip(n, c,i,sum,v,x) {
|
||||
# returns: 1=OK, 0=NG, -1=bad data
|
||||
if (length(n) != 9) {
|
||||
return(-1)
|
||||
}
|
||||
for (i=1; i<=8; i++) {
|
||||
c = substr(n,i,1)
|
||||
if (c ~ /[0-9]/) {
|
||||
v = c
|
||||
}
|
||||
else if (c ~ /[A-Z]/) {
|
||||
v = index("ABCDEFGHIJKLMNOPQRSTUVWXYZ",c) + 9
|
||||
}
|
||||
else if (c == "*") {
|
||||
v = 36
|
||||
}
|
||||
else if (c == "@") {
|
||||
v = 37
|
||||
}
|
||||
else if (c == "#") {
|
||||
v = 38
|
||||
}
|
||||
else {
|
||||
return(-1)
|
||||
}
|
||||
if (i ~ /[02468]/) {
|
||||
v *= 2
|
||||
}
|
||||
sum += int(v / 10) + (v % 10)
|
||||
}
|
||||
x = (10 - (sum % 10)) % 10
|
||||
return(substr(n,9,1) == x ? 1 : 0)
|
||||
}
|
||||
61
Task/CUSIP/Action-/cusip.action
Normal file
61
Task/CUSIP/Action-/cusip.action
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
INCLUDE "D2:CHARTEST.ACT" ;from the Action! Tool Kit
|
||||
|
||||
BYTE FUNC Verify(CHAR ARRAY code)
|
||||
BYTE i,c,v
|
||||
CARD sum
|
||||
|
||||
IF code(0)#9 THEN
|
||||
RETURN (0)
|
||||
ELSEIF IsDigit(code(1))=0 THEN
|
||||
RETURN (0)
|
||||
FI
|
||||
|
||||
sum=0
|
||||
FOR i=2 TO code(0)
|
||||
DO
|
||||
c=code(i)
|
||||
IF IsDigit(c) THEN
|
||||
v=c-'0
|
||||
ELSEIF IsAlpha(c) THEN
|
||||
v=ToUpper(c)-'A+10
|
||||
ELSEIF c='* THEN
|
||||
v=36
|
||||
ELSEIF c='@ THEN
|
||||
v=37
|
||||
ELSEIF c='# THEN
|
||||
v=38
|
||||
ELSE
|
||||
RETURN (0)
|
||||
FI
|
||||
|
||||
IF (i&1)=0 THEN
|
||||
v==*2
|
||||
FI
|
||||
|
||||
sum==+v/10+v MOD 10
|
||||
OD
|
||||
|
||||
v=(10-(sum MOD 10)) MOD 10
|
||||
IF v#code(1)-'0 THEN
|
||||
RETURN (0)
|
||||
FI
|
||||
RETURN (1)
|
||||
|
||||
PROC Test(CHAR ARRAY code)
|
||||
Print(code)
|
||||
IF Verify(code) THEN
|
||||
PrintE(" is valid")
|
||||
ELSE
|
||||
PrintE(" is invalid")
|
||||
FI
|
||||
RETURN
|
||||
|
||||
PROC Main()
|
||||
Put(125) PutE() ;clear the screen
|
||||
Test("037833100")
|
||||
Test("17275R102")
|
||||
Test("38259P508")
|
||||
Test("594918104")
|
||||
Test("68389X106")
|
||||
Test("68389X105")
|
||||
RETURN
|
||||
54
Task/CUSIP/Ada/cusip.ada
Normal file
54
Task/CUSIP/Ada/cusip.ada
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
with Ada.Text_IO;
|
||||
|
||||
procedure Cusip_Test is
|
||||
use Ada.Text_IO;
|
||||
|
||||
subtype Cusip is String (1 .. 9);
|
||||
|
||||
function Check_Cusip (Code : Cusip) return Boolean is
|
||||
Sum : Integer := 0;
|
||||
V : Integer;
|
||||
|
||||
begin
|
||||
for I in Code'First .. Code'Last - 1 loop
|
||||
case Code (I) is
|
||||
when '0' .. '9' =>
|
||||
V := Character'Pos (Code (I)) - Character'Pos ('0');
|
||||
when 'A' .. 'Z' =>
|
||||
V := Character'Pos (Code (I)) - Character'Pos ('A') + 10;
|
||||
when '*' => V := 36;
|
||||
when '@' => V := 37;
|
||||
when '#' => V := 38;
|
||||
when others => return False;
|
||||
end case;
|
||||
|
||||
if I mod 2 = 0 then
|
||||
V := V * 2;
|
||||
end if;
|
||||
|
||||
Sum := Sum + V / 10 + (V mod 10);
|
||||
end loop;
|
||||
|
||||
return (10 - (Sum mod 10)) mod 10 =
|
||||
Character'Pos (Code (Code'Last)) - Character'Pos ('0');
|
||||
end Check_Cusip;
|
||||
|
||||
type Cusip_Array is array (Natural range <>) of Cusip;
|
||||
|
||||
Test_Array : Cusip_Array :=
|
||||
("037833100",
|
||||
"17275R102",
|
||||
"38259P508",
|
||||
"594918104",
|
||||
"68389X106",
|
||||
"68389X105");
|
||||
begin
|
||||
for I in Test_Array'Range loop
|
||||
Put (Test_Array (I) & ": ");
|
||||
if Check_Cusip (Test_Array (I)) then
|
||||
Put_Line ("valid");
|
||||
else
|
||||
Put_Line ("not valid");
|
||||
end if;
|
||||
end loop;
|
||||
end Cusip_Test;
|
||||
280
Task/CUSIP/AppleScript/cusip.applescript
Normal file
280
Task/CUSIP/AppleScript/cusip.applescript
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
use AppleScript version "2.4"
|
||||
use framework "Foundation"
|
||||
use scripting additions
|
||||
|
||||
|
||||
-- isCusip :: String -> Bool
|
||||
on isCusip(s)
|
||||
set cs to "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ*&#"
|
||||
set ns to mapMaybe(elemIndex(cs), s)
|
||||
|
||||
script go
|
||||
on |λ|(f, x)
|
||||
set fx to apply(f, x)
|
||||
(fx div 10) + (fx mod 10)
|
||||
end |λ|
|
||||
end script
|
||||
|
||||
9 = length of ns and item -1 of ns = (10 - (sum(zipWith(go, ¬
|
||||
cycle({my identity, my double}), ¬
|
||||
take(8, ns))) mod 10)) mod 10
|
||||
end isCusip
|
||||
|
||||
|
||||
-------------------------- TEST ---------------------------
|
||||
on run
|
||||
script test
|
||||
on |λ|(s)
|
||||
s & " -> " & isCusip(s)
|
||||
end |λ|
|
||||
end script
|
||||
|
||||
unlines(map(test, ¬
|
||||
{"037833100", "17275R102", "38259P508", ¬
|
||||
"594918104", "68389X106", "68389X105"}))
|
||||
end run
|
||||
|
||||
-- 037833100 -> true
|
||||
-- 17275R102 -> true
|
||||
-- 38259P508 -> true
|
||||
-- 594918104 -> true
|
||||
-- 68389X106 -> false
|
||||
-- 68389X105 -> true
|
||||
|
||||
|
||||
-------------------- GENERIC FUNCTIONS --------------------
|
||||
|
||||
-- Just :: a -> Maybe a
|
||||
on Just(x)
|
||||
-- Constructor for an inhabited Maybe (option type) value.
|
||||
-- Wrapper containing the result of a computation.
|
||||
{type:"Maybe", Nothing:false, Just:x}
|
||||
end Just
|
||||
|
||||
|
||||
-- Nothing :: Maybe a
|
||||
on Nothing()
|
||||
-- Constructor for an empty Maybe (option type) value.
|
||||
-- Empty wrapper returned where a computation is not possible.
|
||||
{type:"Maybe", Nothing:true}
|
||||
end Nothing
|
||||
|
||||
|
||||
-- Tuple (,) :: a -> b -> (a, b)
|
||||
on Tuple(a, b)
|
||||
-- Constructor for a pair of values, possibly of two different types.
|
||||
{type:"Tuple", |1|:a, |2|:b, length:2}
|
||||
end Tuple
|
||||
|
||||
|
||||
-- apply ($) :: (a -> b) -> a -> b
|
||||
on apply(f, x)
|
||||
-- The value of f(x)
|
||||
mReturn(f)'s |λ|(x)
|
||||
end apply
|
||||
|
||||
|
||||
-- cycle :: [a] -> Generator [a]
|
||||
on cycle(xs)
|
||||
script
|
||||
property lng : 1 + (length of xs)
|
||||
property i : missing value
|
||||
on |λ|()
|
||||
if missing value is i then
|
||||
set i to 1
|
||||
else
|
||||
set nxt to (1 + i) mod lng
|
||||
if 0 = ((1 + i) mod lng) then
|
||||
set i to 1
|
||||
else
|
||||
set i to nxt
|
||||
end if
|
||||
end if
|
||||
return item i of xs
|
||||
end |λ|
|
||||
end script
|
||||
end cycle
|
||||
|
||||
|
||||
-- double :: Num -> Num
|
||||
on double(x)
|
||||
2 * x
|
||||
end double
|
||||
|
||||
|
||||
-- elemIndex :: Eq a => [a] -> a -> Maybe Int
|
||||
on elemIndex(xs)
|
||||
script
|
||||
on |λ|(x)
|
||||
set lng to length of xs
|
||||
repeat with i from 1 to lng
|
||||
if x = (item i of xs) then return Just(i - 1)
|
||||
end repeat
|
||||
return Nothing()
|
||||
end |λ|
|
||||
end script
|
||||
end elemIndex
|
||||
|
||||
|
||||
-- identity :: a -> a
|
||||
on identity(x)
|
||||
-- The argument unchanged.
|
||||
x
|
||||
end identity
|
||||
|
||||
|
||||
-- foldl :: (a -> b -> a) -> a -> [b] -> a
|
||||
on foldl(f, startValue, xs)
|
||||
tell mReturn(f)
|
||||
set v to startValue
|
||||
set lng to length of xs
|
||||
repeat with i from 1 to lng
|
||||
set v to |λ|(v, item i of xs, i, xs)
|
||||
end repeat
|
||||
return v
|
||||
end tell
|
||||
end foldl
|
||||
|
||||
|
||||
-- length :: [a] -> Int
|
||||
on |length|(xs)
|
||||
set c to class of xs
|
||||
if list is c or string is c then
|
||||
length of xs
|
||||
else
|
||||
(2 ^ 29 - 1) -- (maxInt - simple proxy for non-finite)
|
||||
end if
|
||||
end |length|
|
||||
|
||||
|
||||
-- map :: (a -> b) -> [a] -> [b]
|
||||
on map(f, xs)
|
||||
-- The list obtained by applying f
|
||||
-- to each element of xs.
|
||||
tell mReturn(f)
|
||||
set lng to length of xs
|
||||
set lst to {}
|
||||
repeat with i from 1 to lng
|
||||
set end of lst to |λ|(item i of xs, i, xs)
|
||||
end repeat
|
||||
return lst
|
||||
end tell
|
||||
end map
|
||||
|
||||
|
||||
-- The mapMaybe function is a version of map which can throw out
|
||||
-- elements. In particular, the functional argument returns
|
||||
-- something of type Maybe b. If this is Nothing, no element is
|
||||
-- added on to the result list. If it just Just b, then b is
|
||||
-- included in the result list.
|
||||
-- mapMaybe :: (a -> Maybe b) -> [a] -> [b]
|
||||
on mapMaybe(mf, xs)
|
||||
script
|
||||
property g : mReturn(mf)
|
||||
on |λ|(a, x)
|
||||
set mb to g's |λ|(x)
|
||||
if Nothing of mb then
|
||||
a
|
||||
else
|
||||
a & (Just of mb)
|
||||
end if
|
||||
end |λ|
|
||||
end script
|
||||
foldl(result, {}, xs)
|
||||
end mapMaybe
|
||||
|
||||
|
||||
-- min :: Ord a => a -> a -> a
|
||||
on min(x, y)
|
||||
if y < x then
|
||||
y
|
||||
else
|
||||
x
|
||||
end if
|
||||
end min
|
||||
|
||||
|
||||
-- mReturn :: First-class m => (a -> b) -> m (a -> b)
|
||||
on mReturn(f)
|
||||
-- 2nd class handler function lifted into 1st class script wrapper.
|
||||
if script is class of f then
|
||||
f
|
||||
else
|
||||
script
|
||||
property |λ| : f
|
||||
end script
|
||||
end if
|
||||
end mReturn
|
||||
|
||||
|
||||
-- sum :: [Num] -> Num
|
||||
on sum(xs)
|
||||
script add
|
||||
on |λ|(a, b)
|
||||
a + b
|
||||
end |λ|
|
||||
end script
|
||||
|
||||
foldl(add, 0, xs)
|
||||
end sum
|
||||
|
||||
|
||||
-- take :: Int -> [a] -> [a]
|
||||
-- take :: Int -> String -> String
|
||||
on take(n, xs)
|
||||
set c to class of xs
|
||||
if list is c then
|
||||
if 0 < n then
|
||||
items 1 thru min(n, length of xs) of xs
|
||||
else
|
||||
{}
|
||||
end if
|
||||
else if string is c then
|
||||
if 0 < n then
|
||||
text 1 thru min(n, length of xs) of xs
|
||||
else
|
||||
""
|
||||
end if
|
||||
else if script is c then
|
||||
set ys to {}
|
||||
repeat with i from 1 to n
|
||||
set v to |λ|() of xs
|
||||
if missing value is v then
|
||||
return ys
|
||||
else
|
||||
set end of ys to v
|
||||
end if
|
||||
end repeat
|
||||
return ys
|
||||
else
|
||||
missing value
|
||||
end if
|
||||
end take
|
||||
|
||||
|
||||
-- unlines :: [String] -> String
|
||||
on unlines(xs)
|
||||
-- A single string formed by the intercalation
|
||||
-- of a list of strings with the newline character.
|
||||
set {dlm, my text item delimiters} to ¬
|
||||
{my text item delimiters, linefeed}
|
||||
set str to xs as text
|
||||
set my text item delimiters to dlm
|
||||
str
|
||||
end unlines
|
||||
|
||||
|
||||
-- zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
|
||||
on zipWith(f, xs, ys)
|
||||
set lng to min(|length|(xs), |length|(ys))
|
||||
if 1 > lng then return {}
|
||||
set xs_ to take(lng, xs) -- Allow for non-finite
|
||||
set ys_ to take(lng, ys) -- generators like cycle etc
|
||||
set lst to {}
|
||||
tell mReturn(f)
|
||||
repeat with i from 1 to lng
|
||||
set end of lst to |λ|(item i of xs_, item i of ys_)
|
||||
end repeat
|
||||
return lst
|
||||
end tell
|
||||
end zipWith
|
||||
27
Task/CUSIP/Arturo/cusip.arturo
Normal file
27
Task/CUSIP/Arturo/cusip.arturo
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
validCUSIP?: function [cusip][
|
||||
s: 0
|
||||
alpha: `A`..`Z`
|
||||
|
||||
loop.with:'i chop cusip 'c [
|
||||
v: 0
|
||||
|
||||
case ø
|
||||
when? [numeric? c] -> v: to :integer to :string c
|
||||
when? [in? c alpha] -> v: (index alpha c) + 1 + 9
|
||||
when? [c = `*`] -> v: 36
|
||||
when? [c = `@`] -> v: 37
|
||||
when? [c = `#`] -> v: 38
|
||||
else []
|
||||
|
||||
if odd? i -> v: 2 * v
|
||||
|
||||
s: s + (v / 10) + (v % 10)
|
||||
]
|
||||
check: (10 - (s % 10)) % 10
|
||||
|
||||
return check = to :integer to :string last cusip
|
||||
]
|
||||
|
||||
loop ["037833100" "17275R102" "38259P508" "594918104" "68389X106" "68389X105"] 'cusip [
|
||||
print [cusip "=>" (validCUSIP? cusip)? -> "VALID" -> "INVALID"]
|
||||
]
|
||||
21
Task/CUSIP/AutoHotkey/cusip-1.ahk
Normal file
21
Task/CUSIP/AutoHotkey/cusip-1.ahk
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
Cusip_Check_Digit(cusip){
|
||||
sum := 0, i := 1, x := StrSplit(cusip)
|
||||
while (i <= 8) {
|
||||
c := x[i]
|
||||
if c is digit
|
||||
v := c
|
||||
else if c is alpha
|
||||
v := Asc(c) - 64 + 9
|
||||
else if (c = "*")
|
||||
v := 36
|
||||
else if (c = "@")
|
||||
v := 37
|
||||
else if (c = "#")
|
||||
v := 38
|
||||
if (i/2 = Floor(i/2))
|
||||
v *= 2
|
||||
sum += Floor(v/10) + Mod(v, 10)
|
||||
i++
|
||||
}
|
||||
return (Mod(10 - Mod(sum, 10), 10) = x[9])
|
||||
}
|
||||
14
Task/CUSIP/AutoHotkey/cusip-2.ahk
Normal file
14
Task/CUSIP/AutoHotkey/cusip-2.ahk
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
data =
|
||||
(
|
||||
037833100
|
||||
17275R102
|
||||
38259P508
|
||||
594918104
|
||||
68389X106
|
||||
68389X105
|
||||
)
|
||||
|
||||
output := "Cusip`t`tValid`n"
|
||||
loop, Parse, data, `n, `r
|
||||
output .= A_LoopField "`t" Cusip_Check_Digit(A_LoopField) "`n"
|
||||
MsgBox % output
|
||||
35
Task/CUSIP/BCPL/cusip.bcpl
Normal file
35
Task/CUSIP/BCPL/cusip.bcpl
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
get "libhdr"
|
||||
|
||||
let validcusip(c) = valof
|
||||
$( let sum = 0
|
||||
unless c%0 = 9 resultis false
|
||||
for i = 1 to 8 do
|
||||
$( let v = ( 2 - (i & 1) ) * valof
|
||||
$( test '0' <= c%i <= '9'
|
||||
then resultis c%i - '0'
|
||||
or test 'A' <= c%i <= 'Z'
|
||||
then resultis 10 + c%i - 'A'
|
||||
or test c%i = '**'
|
||||
then resultis 36
|
||||
or test c%i = '@'
|
||||
then resultis 37
|
||||
or test c%i = '#'
|
||||
then resultis 38
|
||||
else resultis -1
|
||||
$)
|
||||
sum := sum + v/10 + v rem 10
|
||||
$)
|
||||
resultis (10 - (sum rem 10)) rem 10 = c%9 - '0'
|
||||
$)
|
||||
|
||||
let show(c) be
|
||||
writef("%S: %Svalid*N", c, validcusip(c) -> "", "in")
|
||||
|
||||
let start() be
|
||||
$( show("037833100")
|
||||
show("17275R102")
|
||||
show("38259P508")
|
||||
show("594918104")
|
||||
show("68389X106")
|
||||
show("68389X105")
|
||||
$)
|
||||
49
Task/CUSIP/C++/cusip.cpp
Normal file
49
Task/CUSIP/C++/cusip.cpp
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
bool isCusip(const std::string& s) {
|
||||
if (s.size() != 9) return false;
|
||||
|
||||
int sum = 0;
|
||||
for (int i = 0; i <= 7; ++i) {
|
||||
char c = s[i];
|
||||
|
||||
int v;
|
||||
if ('0' <= c && c <= '9') {
|
||||
v = c - '0';
|
||||
} else if ('A' <= c && c <= 'Z') {
|
||||
v = c - '@';
|
||||
} else if (c = '*') {
|
||||
v = 36;
|
||||
} else if (c = '#') {
|
||||
v = 38;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (i % 2 == 1) {
|
||||
v *= 2;
|
||||
}
|
||||
sum += v / 10 + v % 10;
|
||||
}
|
||||
return s[8] - '0' == (10 - (sum % 10)) % 10;
|
||||
}
|
||||
|
||||
int main() {
|
||||
using namespace std;
|
||||
|
||||
vector<string> candidates{
|
||||
"037833100",
|
||||
"17275R102",
|
||||
"38259P508",
|
||||
"594918104",
|
||||
"68389X106",
|
||||
"68389X105"
|
||||
};
|
||||
|
||||
for (auto str : candidates) {
|
||||
auto res = isCusip(str) ? "correct" : "incorrect";
|
||||
cout << str.c_str() << " -> " << res << "\n";
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
48
Task/CUSIP/C-sharp/cusip.cs
Normal file
48
Task/CUSIP/C-sharp/cusip.cs
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace CUSIP {
|
||||
class Program {
|
||||
static bool IsCusip(string s) {
|
||||
if (s.Length != 9) return false;
|
||||
int sum = 0;
|
||||
for (int i = 0; i <= 7; i++) {
|
||||
char c = s[i];
|
||||
|
||||
int v;
|
||||
if (c >= '0' && c <= '9') {
|
||||
v = c - 48;
|
||||
}
|
||||
else if (c >= 'A' && c <= 'Z') {
|
||||
v = c - 55; // lower case letters apparently invalid
|
||||
}
|
||||
else if (c == '*') {
|
||||
v = 36;
|
||||
}
|
||||
else if (c == '#') {
|
||||
v = 38;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
if (i % 2 == 1) v *= 2; // check if odd as using 0-based indexing
|
||||
sum += v / 10 + v % 10;
|
||||
}
|
||||
return s[8] - 48 == (10 - (sum % 10)) % 10;
|
||||
}
|
||||
|
||||
static void Main(string[] args) {
|
||||
List<string> candidates = new List<string>() {
|
||||
"037833100",
|
||||
"17275R102",
|
||||
"38259P508",
|
||||
"594918104",
|
||||
"68389X106",
|
||||
"68389X105"
|
||||
};
|
||||
foreach (var candidate in candidates) {
|
||||
Console.WriteLine("{0} -> {1}", candidate, IsCusip(candidate) ? "correct" : "incorrect");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
53
Task/CUSIP/C/cusip.c
Normal file
53
Task/CUSIP/C/cusip.c
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
#include<stdlib.h>
|
||||
#include<stdio.h>
|
||||
|
||||
int cusipCheck(char str[10]){
|
||||
int sum=0,i,v;
|
||||
|
||||
for(i=0;i<8;i++){
|
||||
if(str[i]>='0'&&str[i]<='9')
|
||||
v = str[i]-'0';
|
||||
else if(str[i]>='A'&&str[i]<='Z')
|
||||
v = (str[i] - 'A' + 10);
|
||||
else if(str[i]=='*')
|
||||
v = 36;
|
||||
else if(str[i]=='@')
|
||||
v = 37;
|
||||
else if(str[i]=='#')
|
||||
v = 38;
|
||||
if(i%2!=0)
|
||||
v*=2;
|
||||
|
||||
sum += ((int)(v/10) + v%10);
|
||||
}
|
||||
return ((10 - (sum%10))%10);
|
||||
}
|
||||
|
||||
int main(int argC,char* argV[])
|
||||
{
|
||||
char cusipStr[10];
|
||||
|
||||
int i,numLines;
|
||||
|
||||
if(argC==1)
|
||||
printf("Usage : %s <full path of CUSIP Data file>",argV[0]);
|
||||
|
||||
else{
|
||||
FILE* fp = fopen(argV[1],"r");
|
||||
|
||||
fscanf(fp,"%d",&numLines);
|
||||
|
||||
printf("CUSIP Verdict\n");
|
||||
printf("-------------------");
|
||||
|
||||
for(i=0;i<numLines;i++){
|
||||
|
||||
fscanf(fp,"%s",cusipStr);
|
||||
|
||||
printf("\n%s : %s",cusipStr,(cusipCheck(cusipStr)==(cusipStr[8]-'0'))?"Valid":"Invalid");
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
33
Task/CUSIP/CLU/cusip.clu
Normal file
33
Task/CUSIP/CLU/cusip.clu
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
valid_cusip = proc (s: string) returns (bool)
|
||||
own chars: string := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ*@#"
|
||||
if string$size(s) ~= 9 then return(false) end
|
||||
sum: int := 0
|
||||
for i: int in int$from_to(1,8) do
|
||||
v: int := string$indexc(s[i], chars)-1
|
||||
if v<0 then return(false) end
|
||||
if i//2=0 then v := v*2 end
|
||||
sum := sum + v/10 + v//10
|
||||
end
|
||||
check: int := (10 - sum // 10) // 10
|
||||
return(check = string$indexc(s[9], chars)-1)
|
||||
end valid_cusip
|
||||
|
||||
start_up = proc ()
|
||||
po: stream := stream$primary_output()
|
||||
cusips: array[string] := array[string]$[
|
||||
"037833100",
|
||||
"17275R102",
|
||||
"38259P508",
|
||||
"594918104",
|
||||
"68389X106",
|
||||
"68389X105"
|
||||
]
|
||||
|
||||
for cusip: string in array[string]$elements(cusips) do
|
||||
stream$puts(po, cusip || ": ")
|
||||
if valid_cusip(cusip)
|
||||
then stream$putl(po, "valid")
|
||||
else stream$putl(po, "invalid")
|
||||
end
|
||||
end
|
||||
end start_up
|
||||
46
Task/CUSIP/Clojure/cusip.clj
Normal file
46
Task/CUSIP/Clojure/cusip.clj
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
(defn- char->value
|
||||
"convert the given char c to a value used to calculate the cusip check sum"
|
||||
[c]
|
||||
(let [int-char (int c)]
|
||||
(cond
|
||||
(and (>= int-char (int \0)) (<= int-char (int \9))) (- int-char 48)
|
||||
(and (>= int-char (int \A)) (<= int-char (int \Z))) (- int-char 55)
|
||||
(= c \*) 36
|
||||
(= c \@) 37
|
||||
(= c \#) 38
|
||||
:else nil)))
|
||||
|
||||
(defn- calc-sum
|
||||
"Calculate cusip sum. nil is returned for an invalid cusip."
|
||||
[cusip]
|
||||
(reduce
|
||||
(fn [sum [i c]]
|
||||
(if-let [v (char->value c)]
|
||||
(let [v (if (= (mod i 2) 1) (* v 2) v)]
|
||||
(+ sum (int (+ (/ v 10) (mod v 10)))))
|
||||
(reduced nil)))
|
||||
0
|
||||
(map-indexed vector (subs cusip 0 8))))
|
||||
|
||||
(defn calc-cusip-checksum
|
||||
"Given a valid 8 or 9 digit cusip, return the 9th checksum digit"
|
||||
[cusip]
|
||||
(when (>= (count cusip) 8)
|
||||
(let [sum (calc-sum cusip)]
|
||||
(when sum
|
||||
(mod (- 10 (mod sum 10)) 10)))))
|
||||
|
||||
(defn is-valid-cusip9?
|
||||
"predicate validating a 9 digit cusip."
|
||||
[cusip9]
|
||||
(when-let [checksum (and (= (count cusip9) 9)
|
||||
(calc-cusip-checksum cusip9))]
|
||||
(= (- (int (nth cusip9 8)) 48)
|
||||
checksum)))
|
||||
|
||||
(defn rosetta-output
|
||||
"show some nice output for the Rosetta Wiki"
|
||||
[]
|
||||
(doseq [cusip ["037833100" "17275R102" "38259P508" "594918104" "68389X106" "68389X105" "EXTRACRD8"
|
||||
"EXTRACRD9" "BADCUSIP!" "683&9X106" "68389x105" "683$9X106" "68389}105" "87264ABE4"]]
|
||||
(println cusip (if (is-valid-cusip9? cusip) "valid" "invalid"))))
|
||||
23
Task/CUSIP/Common-Lisp/cusip.lisp
Normal file
23
Task/CUSIP/Common-Lisp/cusip.lisp
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
(defun char->value (c)
|
||||
(cond ((digit-char-p c 36))
|
||||
((char= c #\*) 36)
|
||||
((char= c #\@) 37)
|
||||
((char= c #\#) 38)
|
||||
(t (error "Invalid character: ~A" c))))
|
||||
|
||||
(defun cusip-p (cusip)
|
||||
(and (= 9 (length cusip))
|
||||
(loop for i from 1 to 8
|
||||
for c across cusip
|
||||
for v = (char->value c)
|
||||
when (evenp i)
|
||||
do (setf v (* 2 v))
|
||||
sum (multiple-value-bind (quot rem) (floor v 10)
|
||||
(+ quot rem))
|
||||
into sum
|
||||
finally (return (eql (digit-char-p (char cusip 8))
|
||||
(mod (- 10 (mod sum 10)) 10))))))
|
||||
|
||||
(defun main ()
|
||||
(dolist (cusip '("037833100" "17275R102" "38259P508" "594918104" "68389X106" "68389X105"))
|
||||
(format t "~A: ~A~%" cusip (cusip-p cusip))))
|
||||
99
Task/CUSIP/D/cusip.d
Normal file
99
Task/CUSIP/D/cusip.d
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
import std.stdio;
|
||||
|
||||
void main(string[] args) {
|
||||
writeln("CUSIP Verdict");
|
||||
foreach(arg; args[1..$]) {
|
||||
writefln("%9s : %s", arg, isValidCusip(arg) ? "Valid" : "Invalid");
|
||||
}
|
||||
}
|
||||
|
||||
class IllegalCharacterException : Exception {
|
||||
this(string msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
|
||||
bool isValidCusip(string cusip) in {
|
||||
assert(cusip.length == 9, "Incorrect cusip length");
|
||||
} body {
|
||||
try {
|
||||
auto check = cusipCheckDigit(cusip);
|
||||
return cusip[8] == ('0' + check);
|
||||
} catch (IllegalCharacterException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
unittest {
|
||||
// Oracle Corporation
|
||||
assertEquals(isValidCusip("68389X105"), true);
|
||||
|
||||
// Oracle Corporation (invalid)
|
||||
assertEquals(isValidCusip("68389X106"), false);
|
||||
}
|
||||
|
||||
int cusipCheckDigit(string cusip) in {
|
||||
assert(cusip.length == 9, "Incorrect cusip length");
|
||||
} body {
|
||||
int sum;
|
||||
for (int i=0; i<8; ++i) {
|
||||
char c = cusip[i];
|
||||
int v;
|
||||
|
||||
switch(c) {
|
||||
case '0': .. case '9':
|
||||
v = c - '0';
|
||||
break;
|
||||
case 'A': .. case 'Z':
|
||||
v = c - 'A' + 10;
|
||||
break;
|
||||
case '*':
|
||||
v = 36;
|
||||
break;
|
||||
case '@':
|
||||
v = 37;
|
||||
break;
|
||||
case '#':
|
||||
v = 38;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalCharacterException("Saw character: " ~ c);
|
||||
}
|
||||
if (i%2 == 1) {
|
||||
v = 2 * v;
|
||||
}
|
||||
|
||||
sum = sum + (v / 10) + (v % 10);
|
||||
}
|
||||
|
||||
return (10 - (sum % 10)) % 10;
|
||||
}
|
||||
|
||||
unittest {
|
||||
// Apple Incorporated
|
||||
assertEquals(cusipCheckDigit("037833100"), 0);
|
||||
|
||||
// Cisco Systems
|
||||
assertEquals(cusipCheckDigit("17275R102"), 2);
|
||||
|
||||
// Google Incorporated
|
||||
assertEquals(cusipCheckDigit("38259P508"), 8);
|
||||
|
||||
// Microsoft Corporation
|
||||
assertEquals(cusipCheckDigit("594918104"), 4);
|
||||
|
||||
// Oracle Corporation
|
||||
assertEquals(cusipCheckDigit("68389X105"), 5);
|
||||
}
|
||||
|
||||
version(unittest) {
|
||||
void assertEquals(T)(T actual, T expected) {
|
||||
import core.exception;
|
||||
import std.conv;
|
||||
if (actual != expected) {
|
||||
throw new AssertError("Actual [" ~ to!string(actual) ~ "]; Expected [" ~ to!string(expected) ~ "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Invoke with `cusip 037833100 17275R102 38259P508 594918104 68389X106 68389X105`
|
||||
48
Task/CUSIP/Delphi/cusip.delphi
Normal file
48
Task/CUSIP/Delphi/cusip.delphi
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
type TCUSIPInfo = record
|
||||
ID,Company: string;
|
||||
end;
|
||||
|
||||
var CUSIPArray: array [0..5] of TCUSIPInfo = (
|
||||
(ID:'037833100'; Company: 'Apple Incorporated'),
|
||||
(ID:'17275R102'; Company: 'Cisco Systems'),
|
||||
(ID:'38259P508'; Company: 'Google Incorporated'),
|
||||
(ID:'594918104'; Company: 'Microsoft Corporation'),
|
||||
(ID:'68389X106'; Company: 'Oracle Corporation'),
|
||||
(ID:'68389X105'; Company: 'Oracle Corporation'));
|
||||
|
||||
function IsValidCUSIP(Info: TCUSIPInfo): boolean;
|
||||
{Calculate checksum on first 7 chars of CUSIP }
|
||||
{And compare with the last char - the checksum char}
|
||||
var I,V,Sum: integer;
|
||||
var C: char;
|
||||
begin
|
||||
Sum:=0;
|
||||
for I:=1 to Length(Info.ID)-1 do
|
||||
begin
|
||||
C:=Info.ID[I];
|
||||
if C in ['0'..'9'] then V:=byte(C)-$30
|
||||
else if C in ['A'..'Z'] then V:=(byte(C)-$40) + 9
|
||||
else case C of
|
||||
'*': V:=36;
|
||||
'@': V:=37;
|
||||
'#': V:=38;
|
||||
end;
|
||||
if (I and 1)=0 then V:=V*2;
|
||||
Sum:=Sum + (V div 10) + (V mod 10);
|
||||
end;
|
||||
Sum:=(10 - (Sum mod 10)) mod 10;
|
||||
Result:=StrToInt(Info.ID[Length(Info.ID)])=Sum;
|
||||
end;
|
||||
|
||||
|
||||
procedure TestCUSIPList(Memo: TMemo);
|
||||
{Test every item in the CSUIP array}
|
||||
var I: integer;
|
||||
var S: string;
|
||||
begin
|
||||
for I:=0 to High(CUSIPArray) do
|
||||
begin
|
||||
if IsValidCUSIP(CUSIPArray[I]) then S:='Valid' else S:='Invalid';
|
||||
Memo.Lines.Add(CUSIPArray[I].ID+' '+CUSIPArray[I].Company+': '+S);
|
||||
end;
|
||||
end;
|
||||
38
Task/CUSIP/Dyalect/cusip.dyalect
Normal file
38
Task/CUSIP/Dyalect/cusip.dyalect
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
func isCusip(s) {
|
||||
if s.Length() != 9 { return false }
|
||||
var sum = 0
|
||||
for i in 0..7 {
|
||||
var c = s[i]
|
||||
var v =
|
||||
match c {
|
||||
'0'..'9' => c.Order() - 48,
|
||||
'A'..'Z' => c.Order() - 55,
|
||||
'*' => 36,
|
||||
'@' => 37,
|
||||
'#' => 38,
|
||||
_ => false
|
||||
}
|
||||
if i % 2 == 1 { v *= 2 }
|
||||
sum += v / 10 + v % 10
|
||||
}
|
||||
s[8].Order() - 48 == (10 - (sum % 10)) % 10
|
||||
}
|
||||
|
||||
var candidates = [
|
||||
"037833100",
|
||||
"17275R102",
|
||||
"38259P508",
|
||||
"594918104",
|
||||
"68389X106",
|
||||
"68389X105"
|
||||
]
|
||||
|
||||
for candidate in candidates {
|
||||
var b =
|
||||
if isCusip(candidate) {
|
||||
"correct"
|
||||
} else {
|
||||
"incorrect"
|
||||
}
|
||||
print("\(candidate) -> \(b)")
|
||||
}
|
||||
39
Task/CUSIP/Excel/cusip-1.excel
Normal file
39
Task/CUSIP/Excel/cusip-1.excel
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
=LAMBDA(s,
|
||||
LET(
|
||||
ns, VLOOKUP(
|
||||
CHARS(s), CUSIPMAP, 2, FALSE
|
||||
),
|
||||
|
||||
AND(
|
||||
9 = COLUMNS(ns),
|
||||
LET(
|
||||
firstEight, INITCOLS(ns),
|
||||
|
||||
ixs, SEQUENCE(1, 8),
|
||||
|
||||
evensDoubled, IF(ISEVEN(ixs),
|
||||
2 * INDEX(firstEight, 1, ixs),
|
||||
INDEX(firstEight, 1, ixs)
|
||||
),
|
||||
|
||||
LASTCOL(ns) = MOD(
|
||||
10 - MOD(
|
||||
SUM(
|
||||
QUOTIENT(evensDoubled, 10),
|
||||
MOD(evensDoubled, 10)
|
||||
),
|
||||
10
|
||||
),
|
||||
10
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
CUSIPMAP
|
||||
={"0",0;"1",1;"2",2;"3",3;"4",4;"5",5;"6",6;"7",7;"8",8;"9",9;"A",
|
||||
10;"B",11;"C",12;"D",13;"E",14;"F",15;"G",16;"H",17;"I",18;"J",19;"K",
|
||||
20;"L",21;"M",22;"N",23;"O",24;"P",25;"Q",26;"R",27;"S",28;"T",29;"U",
|
||||
30;"V",31;"W",32;"X",33;"Y",34;"Z",35;"*",36;"@",37;"#",38}
|
||||
31
Task/CUSIP/Excel/cusip-2.excel
Normal file
31
Task/CUSIP/Excel/cusip-2.excel
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
CHARS
|
||||
=LAMBDA(s,
|
||||
MID(
|
||||
s,
|
||||
SEQUENCE(1, LEN(s), 1, 1),
|
||||
1
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
INITCOLS
|
||||
=LAMBDA(xs,
|
||||
INDEX(
|
||||
xs,
|
||||
SEQUENCE(
|
||||
1,
|
||||
COLUMNS(xs) - 1,
|
||||
1,
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
LASTCOL
|
||||
=LAMBDA(xs,
|
||||
INDEX(
|
||||
xs,
|
||||
SEQUENCE(ROWS(xs), 1, 1, 1),
|
||||
COLUMNS(xs)
|
||||
)
|
||||
)
|
||||
4
Task/CUSIP/F-Sharp/cusip.fs
Normal file
4
Task/CUSIP/F-Sharp/cusip.fs
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
// Validate CUSIP: Nigel Galloway. June 2nd., 2021
|
||||
let fN=function n when n>47 && n<58->n-48 |n when n>64 && n<91->n-55 |42->36 |64->37 |_->38
|
||||
let cD(n:string)=(10-(fst((n.[0..7])|>Seq.fold(fun(z,n)g->let g=(fN(int g))*(n+1) in (z+g/10+g%10,(n+1)%2))(0,0)))%10)%10=int(n.[8])-48
|
||||
["037833100";"17275R102";"38259P508";"594918104";"68389X103";"68389X105"]|>List.iter(fun n->printfn "CUSIP %s is %s" n (if cD n then "valid" else "invalid"))
|
||||
18
Task/CUSIP/Factor/cusip.factor
Normal file
18
Task/CUSIP/Factor/cusip.factor
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
USING: combinators.short-circuit formatting kernel math
|
||||
math.parser qw regexp sequences unicode ;
|
||||
IN: rosetta-code.cusip
|
||||
|
||||
: cusip-check-digit ( seq -- n )
|
||||
but-last-slice [
|
||||
[ dup alpha? [ digit> ] [ "*@#" index 36 + ] if ] dip
|
||||
odd? [ 2 * ] when 10 /mod +
|
||||
] map-index sum 10 mod 10 swap - 10 mod ;
|
||||
|
||||
: cusip? ( seq -- ? )
|
||||
{
|
||||
[ R/ [0-9A-Z*@#]+/ matches? ]
|
||||
[ [ last digit> ] [ cusip-check-digit ] bi = ]
|
||||
} 1&& ;
|
||||
|
||||
qw{ 037833100 17275R102 38259P508 594918104 68389X106 68389X105 }
|
||||
[ dup cusip? "correct" "incorrect" ? "%s -> %s\n" printf ] each
|
||||
34
Task/CUSIP/Fortran/cusip.f
Normal file
34
Task/CUSIP/Fortran/cusip.f
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
CHARACTER*1 FUNCTION CUSIPCHECK(TEXT) !Determines the check sum character.
|
||||
Committee on Uniform Security Identification Purposes, of the American (i.e. USA) Bankers' Association.
|
||||
CHARACTER*8 TEXT !Specifically, an eight-symbol code.
|
||||
CHARACTER*(*) VALID !These only are valid.
|
||||
PARAMETER (VALID = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ*@#")
|
||||
INTEGER I,V,S !Assistants.
|
||||
S = 0 !Start the checksum.
|
||||
DO I = 1,LEN(TEXT) !Step through the text.
|
||||
V = INDEX(VALID,TEXT(I:I)) - 1 !Since counting starts with one.
|
||||
IF (MOD(I,2).EQ.0) V = V*2 !V = V*(2 - MOD(I,2))?
|
||||
S = S + V/10 + MOD(V,10) !Specified calculation.
|
||||
END DO !On to the next character.
|
||||
I = MOD(10 - MOD(S,10),10) + 1 !Again, counting starts with one.
|
||||
CUSIPCHECK = VALID(I:I) !Thanks to the MOD 10, surely a digit.
|
||||
END FUNCTION CUSIPCHECK !No checking for invalid input...
|
||||
|
||||
PROGRAM POKE !Just to try it out.
|
||||
INTEGER I,N !Assistants.
|
||||
PARAMETER (N = 6) !A whole lot of blather
|
||||
CHARACTER*9 CUSIP(N) !Just to have an array of test codes.
|
||||
DATA CUSIP/ !Here they are, as specified.
|
||||
1 "037833100",
|
||||
2 "17275R102",
|
||||
3 "38259P508",
|
||||
4 "594918104",
|
||||
5 "68389X106",
|
||||
6 "68389X105"/
|
||||
CHARACTER*1 CUSIPCHECK !Needed as no use of the MODULE protocol.
|
||||
|
||||
DO I = 1,N !"More than two? Use a DO..."
|
||||
WRITE (6,*) CUSIP(I),CUSIPCHECK(CUSIP(I)(1:8)).EQ.CUSIP(I)(9:9)
|
||||
END DO
|
||||
|
||||
END
|
||||
63
Task/CUSIP/FreeBASIC/cusip.basic
Normal file
63
Task/CUSIP/FreeBASIC/cusip.basic
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
' version 04-04-2017
|
||||
' compile with: fbc -s console
|
||||
|
||||
sub cusip(input_str As String)
|
||||
|
||||
Print input_str;
|
||||
If Len(input_str) <> 9 Then
|
||||
Print " length is incorrect, invalid cusip"
|
||||
Return
|
||||
End If
|
||||
|
||||
Dim As Long i, v , sum
|
||||
Dim As UByte x
|
||||
|
||||
For i = 1 To 8
|
||||
x = input_str[i-1]
|
||||
Select Case x
|
||||
Case Asc("0") To Asc("9")
|
||||
v = x - Asc("0")
|
||||
Case Asc("A") To Asc("Z")
|
||||
v = x - Asc("A") + 1 + 9
|
||||
Case Asc("*")
|
||||
v= 36
|
||||
Case Asc("@")
|
||||
v = 37
|
||||
Case Asc("#")
|
||||
v = 38
|
||||
Case Else
|
||||
Print " found a invalid character, invalid cusip"
|
||||
return
|
||||
End Select
|
||||
|
||||
If (i And 1) = 0 Then v = v * 2
|
||||
sum = sum + v \ 10 + v Mod 10
|
||||
Next
|
||||
|
||||
sum = (10 - (sum Mod 10)) Mod 10
|
||||
If sum = (input_str[8] - Asc("0")) Then
|
||||
Print " is valid"
|
||||
Else
|
||||
Print " is invalid"
|
||||
End If
|
||||
|
||||
End Sub
|
||||
|
||||
' ------=< MAIN >=------
|
||||
|
||||
Data "037833100", "17275R102", "38259P508"
|
||||
Data "594918104", "68389X106", "68389X105"
|
||||
|
||||
Dim As String input_str
|
||||
|
||||
Print
|
||||
For i As Integer = 1 To 6
|
||||
Read input_str
|
||||
cusip(input_str)
|
||||
Next
|
||||
|
||||
' empty keyboard buffer
|
||||
While InKey <> "" : Wend
|
||||
Print : Print "hit any key to end program"
|
||||
Sleep
|
||||
End
|
||||
49
Task/CUSIP/FutureBasic/cusip.basic
Normal file
49
Task/CUSIP/FutureBasic/cusip.basic
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
include "NSLog.incl"
|
||||
|
||||
local fn VerifyCUSIP( cusipStr as CFStringRef ) as CFStringRef
|
||||
NSUInteger i, v, sum = 0, count = len(cusipStr)
|
||||
CFStringRef resultStr
|
||||
|
||||
if count != 9 then exit fn = @"Invalid length"
|
||||
|
||||
for i = 0 to 7
|
||||
unichar x = fn StringCharacterAtIndex( cusipStr, i )
|
||||
select x
|
||||
case _"*" : v = 36
|
||||
case _"@" : v = 37
|
||||
case _"#" : v = 38
|
||||
case else
|
||||
if ( x >= _"0" and x <= _"9" )
|
||||
v = x - _"0"
|
||||
else
|
||||
if ( x >= _"A" and x <= _"Z" )
|
||||
v = x - _"A" + 10
|
||||
else
|
||||
exit fn = fn StringWithFormat( @"Invalid character: %c", x )
|
||||
end if
|
||||
end if
|
||||
end select
|
||||
|
||||
if ( i and 1 ) then v = v * 2
|
||||
|
||||
sum += (v / 10) + (v mod 10)
|
||||
next
|
||||
sum = ((10-(sum mod 10)) mod 10)
|
||||
|
||||
if (sum == ( fn StringCharacterAtIndex( cusipStr, 8 ) - _"0" ))
|
||||
resultStr = @"Valid"
|
||||
else
|
||||
resultStr = @"Invalid"
|
||||
end If
|
||||
end fn = resultStr
|
||||
|
||||
NSLog( @"0378331009: %@", fn VerifyCUSIP( @"0378331009" ) ) // Invalid length expected
|
||||
NSLog( @"037833100: %@", fn VerifyCUSIP( @"037833100" ) ) // Valid expected
|
||||
NSLog( @"17275R102: %@", fn VerifyCUSIP( @"17275R102" ) ) // Valid expected
|
||||
NSLog( @"38259P508: %@", fn VerifyCUSIP( @"38259P508" ) ) // Valid expected
|
||||
NSLog( @"594918104: %@", fn VerifyCUSIP( @"594918104" ) ) // Valid expected
|
||||
NSLog( @"68389X106: %@", fn VerifyCUSIP( @"68389X106" ) ) // Invalid expected
|
||||
NSLog( @"68389X105: %@", fn VerifyCUSIP( @"68389X105" ) ) // Valid expected
|
||||
NSLog( @"683&9X105: %@", fn VerifyCUSIP( @"683&9X105" ) ) // Invalid character expected: &
|
||||
|
||||
HandleEvents
|
||||
50
Task/CUSIP/Go/cusip.go
Normal file
50
Task/CUSIP/Go/cusip.go
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func isCusip(s string) bool {
|
||||
if len(s) != 9 { return false }
|
||||
sum := 0
|
||||
for i := 0; i < 8; i++ {
|
||||
c := s[i]
|
||||
var v int
|
||||
switch {
|
||||
case c >= '0' && c <= '9':
|
||||
v = int(c) - 48
|
||||
case c >= 'A' && c <= 'Z':
|
||||
v = int(c) - 55
|
||||
case c == '*':
|
||||
v = 36
|
||||
case c == '@':
|
||||
v = 37
|
||||
case c == '#':
|
||||
v = 38
|
||||
default:
|
||||
return false
|
||||
}
|
||||
if i % 2 == 1 { v *= 2 } // check if odd as using 0-based indexing
|
||||
sum += v/10 + v%10
|
||||
}
|
||||
return int(s[8]) - 48 == (10 - (sum%10)) % 10
|
||||
}
|
||||
|
||||
func main() {
|
||||
candidates := []string {
|
||||
"037833100",
|
||||
"17275R102",
|
||||
"38259P508",
|
||||
"594918104",
|
||||
"68389X106",
|
||||
"68389X105",
|
||||
}
|
||||
|
||||
for _, candidate := range candidates {
|
||||
var b string
|
||||
if isCusip(candidate) {
|
||||
b = "correct"
|
||||
} else {
|
||||
b = "incorrect"
|
||||
}
|
||||
fmt.Printf("%s -> %s\n", candidate, b)
|
||||
}
|
||||
}
|
||||
40
Task/CUSIP/Groovy/cusip.groovy
Normal file
40
Task/CUSIP/Groovy/cusip.groovy
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
class Cusip {
|
||||
private static Boolean isCusip(String s) {
|
||||
if (s.length() != 9) return false
|
||||
int sum = 0
|
||||
for (int i = 0; i <= 7; i++) {
|
||||
char c = s.charAt(i)
|
||||
|
||||
int v
|
||||
if (c >= ('0' as char) && c <= ('9' as char)) {
|
||||
v = c - 48
|
||||
} else if (c >= ('A' as char) && c <= ('Z' as char)) {
|
||||
v = c - 55 // lower case letters apparently invalid
|
||||
} else if (c == '*' as char) {
|
||||
v = 36
|
||||
} else if (c == '@' as char) {
|
||||
v = 37
|
||||
} else if (c == '#' as char) {
|
||||
v = 38
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
if (i % 2 == 1) v *= 2 // check if odd as using 0-based indexing
|
||||
sum += v / 10 + v % 10
|
||||
}
|
||||
return s.charAt(8) - 48 == (10 - (sum % 10)) % 10
|
||||
}
|
||||
|
||||
static void main(String[] args) {
|
||||
List<String> candidates=new ArrayList<>()
|
||||
candidates.add("037833100")
|
||||
candidates.add("17275R102")
|
||||
candidates.add("38259P508")
|
||||
candidates.add("594918104")
|
||||
candidates.add("68389X106")
|
||||
candidates.add("68389X105")
|
||||
for (String candidate : candidates) {
|
||||
System.out.printf("%s -> %s%n", candidate, isCusip(candidate) ? "correct" : "incorrect")
|
||||
}
|
||||
}
|
||||
}
|
||||
44
Task/CUSIP/Haskell/cusip-1.hs
Normal file
44
Task/CUSIP/Haskell/cusip-1.hs
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
import Data.List(elemIndex)
|
||||
|
||||
data Result = Valid | BadCheck | TooLong | TooShort | InvalidContent deriving Show
|
||||
|
||||
-- convert a list of Maybe to a Maybe list.
|
||||
-- result is Nothing if any of values from the original list are Nothing
|
||||
allMaybe :: [Maybe a] -> Maybe [a]
|
||||
allMaybe = sequence
|
||||
|
||||
toValue :: Char -> Maybe Int
|
||||
toValue c = elemIndex c $ ['0'..'9'] ++ ['A'..'Z'] ++ "*@#"
|
||||
|
||||
-- check a list of ints to see if they represent a valid CUSIP
|
||||
valid :: [Int] -> Bool
|
||||
valid ns0 =
|
||||
let -- multiply values with even index by 2
|
||||
ns1 = zipWith (\i n -> (if odd i then n else 2*n)) [1..] $ take 8 ns0
|
||||
|
||||
-- apply div/mod formula from site and sum up results
|
||||
sm = sum $ fmap (\s -> ( s `div` 10 ) + s `mod` 10) ns1
|
||||
|
||||
in -- apply mod/mod formula from site and compare to last value in list
|
||||
ns0!!8 == (10 - (sm `mod` 10)) `mod` 10
|
||||
|
||||
-- check a String to see if it represents a valid CUSIP
|
||||
checkCUSIP :: String -> Result
|
||||
checkCUSIP cs
|
||||
| l < 9 = TooShort
|
||||
| l > 9 = TooLong
|
||||
| otherwise = case allMaybe (fmap toValue cs) of
|
||||
Nothing -> InvalidContent
|
||||
Just ns -> if valid ns then Valid else BadCheck
|
||||
where l = length cs
|
||||
|
||||
testData =
|
||||
[ "037833100"
|
||||
, "17275R102"
|
||||
, "38259P508"
|
||||
, "594918104"
|
||||
, "68389X106"
|
||||
, "68389X105"
|
||||
]
|
||||
|
||||
main = mapM_ putStrLn (fmap (\s -> s ++ ": " ++ show (checkCUSIP s)) testData)
|
||||
37
Task/CUSIP/Haskell/cusip-2.hs
Normal file
37
Task/CUSIP/Haskell/cusip-2.hs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import qualified Data.Map as M (Map, fromList, lookup)
|
||||
import Data.Maybe (fromMaybe)
|
||||
|
||||
-------------------------- CUSIP -------------------------
|
||||
|
||||
cusipMap :: M.Map Char Int
|
||||
cusipMap =
|
||||
M.fromList $
|
||||
zip (['0' .. '9'] <> ['A' .. 'Z'] <> "*@#") [0 ..]
|
||||
|
||||
cusipValid :: String -> Bool
|
||||
cusipValid s =
|
||||
let ns = (fromMaybe [] . traverse (`M.lookup` cusipMap)) s
|
||||
in (9 == length ns)
|
||||
&& let qrSum =
|
||||
sum $
|
||||
( [quot, rem]
|
||||
<*> zipWith
|
||||
id
|
||||
(cycle [id, (* 2)])
|
||||
(take 8 ns)
|
||||
)
|
||||
<*> [10]
|
||||
in last ns == rem (10 - rem qrSum 10) 10
|
||||
|
||||
--------------------------- TEST -------------------------
|
||||
main :: IO ()
|
||||
main =
|
||||
mapM_
|
||||
(print . ((,) <*> cusipValid))
|
||||
[ "037833100",
|
||||
"17275R102",
|
||||
"38259P508",
|
||||
"594918104",
|
||||
"68389X106",
|
||||
"68389X105"
|
||||
]
|
||||
40
Task/CUSIP/Icon/cusip.icon
Normal file
40
Task/CUSIP/Icon/cusip.icon
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
# cusip.icn -- Committee on Uniform Security Identification Procedures
|
||||
|
||||
procedure main()
|
||||
local code, codes
|
||||
codes := ["037833100", "17275R102", "38259P508",
|
||||
"594918104", "68389X106", "68389X105"]
|
||||
while code := pop(codes) do {
|
||||
writes(code, " : ")
|
||||
if check_code(code) then
|
||||
write("valid.")
|
||||
else write("not valid.")
|
||||
}
|
||||
end
|
||||
|
||||
procedure check_code(c)
|
||||
local p, sum, value
|
||||
static codetable
|
||||
initial codetable := buildtable()
|
||||
|
||||
sum := 0
|
||||
value := 0
|
||||
every p := 1 to 8 do {
|
||||
if p % 2 = 1 then # odd position
|
||||
value := codetable[c[p]]
|
||||
else # even position
|
||||
value := 2 * codetable[c[p]]
|
||||
sum +:= (value / 10) + (value % 10)
|
||||
}
|
||||
sum := (10 - (sum % 10)) % 10
|
||||
if sum = c[9] then return else fail
|
||||
end
|
||||
|
||||
procedure buildtable()
|
||||
local chars, n, t
|
||||
t := table()
|
||||
chars := &digits || &ucase || "*@#"
|
||||
every n := 1 to *chars do
|
||||
t[chars[n]] := (n - 1)
|
||||
return t
|
||||
end
|
||||
3
Task/CUSIP/J/cusip-1.j
Normal file
3
Task/CUSIP/J/cusip-1.j
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
ccd =. 10 | 10 - 10 | [: +/ [: , 10 (#.^:_1) (8 $ 1 2) * '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ*@#' i. ]
|
||||
ccd '68389X10'
|
||||
5
|
||||
10
Task/CUSIP/J/cusip-2.j
Normal file
10
Task/CUSIP/J/cusip-2.j
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
CUSIPcheckdigit =. 3 : 0
|
||||
assert. 8 = $ y NB. Only accept an 8-element long list
|
||||
assert. */ y e. '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ*@#' NB. Only accept characters from the list of 38
|
||||
values =. (8 $ 1 2) * '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ*@#' i. ] NB. Verb to translate characters and then double every second value.
|
||||
sumdigits =. +/@,@(10 10&#:) NB. Verb to sum the base-10 digits in a numerical array
|
||||
invertedmod =. 10 | 10 - 10 | ] NB. Verb to find the mod-10 of 10 minus mod-10
|
||||
": invertedmod sumdigits values y NB. Return the check digit as a character
|
||||
)
|
||||
addCUSIPcheckdigit =: , CUSIPcheckdigit
|
||||
verifyCUSIPcheckdigit =: {: = CUSIPcheckdigit@}:
|
||||
16
Task/CUSIP/J/cusip-3.j
Normal file
16
Task/CUSIP/J/cusip-3.j
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
addCUSIPcheckdigit '68389X10'
|
||||
68389X105
|
||||
verifyCUSIPcheckdigit '68389X106'
|
||||
0
|
||||
verifyCUSIPcheckdigit '68389X105'
|
||||
1
|
||||
samples =: '037833100', '17275R102', '38259P508', '594918104', '68389X106',: '68389X105'
|
||||
samples ; verifyCUSIPcheckdigit"1 samples
|
||||
┌─────────┬─┐
|
||||
│037833100│1│
|
||||
│17275R102│1│
|
||||
│38259P508│1│
|
||||
│594918104│1│
|
||||
│68389X106│0│
|
||||
│68389X105│1│
|
||||
└─────────┴─┘
|
||||
39
Task/CUSIP/Java/cusip.java
Normal file
39
Task/CUSIP/Java/cusip.java
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
import java.util.List;
|
||||
|
||||
public class Cusip {
|
||||
private static Boolean isCusip(String s) {
|
||||
if (s.length() != 9) return false;
|
||||
int sum = 0;
|
||||
for (int i = 0; i <= 7; i++) {
|
||||
char c = s.charAt(i);
|
||||
|
||||
int v;
|
||||
if (c >= '0' && c <= '9') {
|
||||
v = c - 48;
|
||||
} else if (c >= 'A' && c <= 'Z') {
|
||||
v = c - 55; // lower case letters apparently invalid
|
||||
} else if (c == '*') {
|
||||
v = 36;
|
||||
} else if (c == '@') {
|
||||
v = 37;
|
||||
} else if (c == '#') {
|
||||
v = 38;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (i % 2 == 1) v *= 2; // check if odd as using 0-based indexing
|
||||
sum += v / 10 + v % 10;
|
||||
}
|
||||
return s.charAt(8) - 48 == (10 - (sum % 10)) % 10;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
List<String> candidates = List.of(
|
||||
"037833100", "17275R102", "38259P508", "594918104", "68389X106", "68389X105", "EXTRACRD8",
|
||||
"EXTRACRD9", "BADCUSIP!", "683&9X106", "68389x105", "683$9X106", "68389}105", "87264ABE4"
|
||||
);
|
||||
for (String candidate : candidates) {
|
||||
System.out.printf("%s -> %s%n", candidate, isCusip(candidate) ? "correct" : "incorrect");
|
||||
}
|
||||
}
|
||||
}
|
||||
429
Task/CUSIP/JavaScript/cusip.js
Normal file
429
Task/CUSIP/JavaScript/cusip.js
Normal file
|
|
@ -0,0 +1,429 @@
|
|||
(() => {
|
||||
'use strict';
|
||||
|
||||
// cusipValid = Dict Char Int -> String -> Bool
|
||||
const cusipValid = charMap => s => {
|
||||
const
|
||||
ns = fromMaybe([])(
|
||||
traverse(flip(lookupDict)(charMap))(
|
||||
chars(s)
|
||||
)
|
||||
);
|
||||
return 9 === ns.length && (
|
||||
last(ns) === rem(
|
||||
10 - rem(
|
||||
sum(apList(
|
||||
apList([quot, rem])(
|
||||
zipWith(identity)(
|
||||
cycle([identity, x => 2 * x])
|
||||
)(take(8)(ns))
|
||||
)
|
||||
)([10]))
|
||||
)(10)
|
||||
)(10)
|
||||
);
|
||||
};
|
||||
|
||||
//----------------------- TEST ------------------------
|
||||
// main :: IO ()
|
||||
const main = () => {
|
||||
|
||||
// cusipMap :: Dict Char Int
|
||||
const cusipMap = dictFromList(
|
||||
zip(chars(
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ*@#"
|
||||
))(enumFrom(0)));
|
||||
|
||||
console.log(unlines(map(
|
||||
apFn(
|
||||
s => validity => s + ' -> ' + str(validity)
|
||||
)(cusipValid(cusipMap))
|
||||
)([
|
||||
'037833100',
|
||||
'17275R102',
|
||||
'38259P508',
|
||||
'594918104',
|
||||
'68389X106',
|
||||
'68389X105'
|
||||
])));
|
||||
};
|
||||
|
||||
|
||||
//----------------- GENERIC FUNCTIONS -----------------
|
||||
|
||||
// Just :: a -> Maybe a
|
||||
const Just = x => ({
|
||||
type: 'Maybe',
|
||||
Nothing: false,
|
||||
Just: x
|
||||
});
|
||||
|
||||
|
||||
// Nothing :: Maybe a
|
||||
const Nothing = () => ({
|
||||
type: 'Maybe',
|
||||
Nothing: true,
|
||||
});
|
||||
|
||||
|
||||
// Tuple (,) :: a -> b -> (a, b)
|
||||
const Tuple = a =>
|
||||
b => ({
|
||||
type: 'Tuple',
|
||||
'0': a,
|
||||
'1': b,
|
||||
length: 2
|
||||
});
|
||||
|
||||
|
||||
// apFn :: (a -> b -> c) -> (a -> b) -> a -> c
|
||||
const apFn = f =>
|
||||
// Applicative instance for functions.
|
||||
// f(x) applied to g(x).
|
||||
g => x => f(x)(
|
||||
g(x)
|
||||
);
|
||||
|
||||
|
||||
// apList (<*>) :: [(a -> b)] -> [a] -> [b]
|
||||
const apList = fs =>
|
||||
// The sequential application of each of a list
|
||||
// of functions to each of a list of values.
|
||||
xs => fs.flatMap(
|
||||
f => xs.map(f)
|
||||
);
|
||||
|
||||
|
||||
// append (++) :: [a] -> [a] -> [a]
|
||||
// append (++) :: String -> String -> String
|
||||
const append = xs =>
|
||||
// A list or string composed by
|
||||
// the concatenation of two others.
|
||||
ys => xs.concat(ys);
|
||||
|
||||
|
||||
// chars :: String -> [Char]
|
||||
const chars = s =>
|
||||
s.split('');
|
||||
|
||||
|
||||
// cons :: a -> [a] -> [a]
|
||||
const cons = x =>
|
||||
xs => Array.isArray(xs) ? (
|
||||
[x].concat(xs)
|
||||
) : 'GeneratorFunction' !== xs
|
||||
.constructor.constructor.name ? (
|
||||
x + xs
|
||||
) : ( // cons(x)(Generator)
|
||||
function*() {
|
||||
yield x;
|
||||
let nxt = xs.next()
|
||||
while (!nxt.done) {
|
||||
yield nxt.value;
|
||||
nxt = xs.next();
|
||||
}
|
||||
}
|
||||
)();
|
||||
|
||||
|
||||
// cycle :: [a] -> Generator [a]
|
||||
function* cycle(xs) {
|
||||
const lng = xs.length;
|
||||
let i = 0;
|
||||
while (true) {
|
||||
yield(xs[i])
|
||||
i = (1 + i) % lng;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// dictFromList :: [(k, v)] -> Dict
|
||||
const dictFromList = kvs =>
|
||||
Object.fromEntries(kvs);
|
||||
|
||||
|
||||
// enumFrom :: Enum a => a -> [a]
|
||||
function* enumFrom(x) {
|
||||
// A non-finite succession of enumerable
|
||||
// values, starting with the value x.
|
||||
let v = x;
|
||||
while (true) {
|
||||
yield v;
|
||||
v = succ(v);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// flip :: (a -> b -> c) -> b -> a -> c
|
||||
const flip = f =>
|
||||
1 < f.length ? (
|
||||
(a, b) => f(b, a)
|
||||
) : (x => y => f(y)(x));
|
||||
|
||||
|
||||
// fromEnum :: Enum a => a -> Int
|
||||
const fromEnum = x =>
|
||||
typeof x !== 'string' ? (
|
||||
x.constructor === Object ? (
|
||||
x.value
|
||||
) : parseInt(Number(x))
|
||||
) : x.codePointAt(0);
|
||||
|
||||
|
||||
// fromMaybe :: a -> Maybe a -> a
|
||||
const fromMaybe = def =>
|
||||
// A default value if mb is Nothing
|
||||
// or the contents of mb.
|
||||
mb => mb.Nothing ? def : mb.Just;
|
||||
|
||||
|
||||
// fst :: (a, b) -> a
|
||||
const fst = tpl =>
|
||||
// First member of a pair.
|
||||
tpl[0];
|
||||
|
||||
|
||||
// identity :: a -> a
|
||||
const identity = x =>
|
||||
// The identity function. (`id`, in Haskell)
|
||||
x;
|
||||
|
||||
|
||||
// last :: [a] -> a
|
||||
const last = xs =>
|
||||
// The last item of a list.
|
||||
0 < xs.length ? xs.slice(-1)[0] : undefined;
|
||||
|
||||
|
||||
// length :: [a] -> Int
|
||||
const length = xs =>
|
||||
// Returns Infinity over objects without finite
|
||||
// length. This enables zip and zipWith to choose
|
||||
// the shorter argument when one is non-finite,
|
||||
// like cycle, repeat etc
|
||||
(Array.isArray(xs) || 'string' === typeof xs) ? (
|
||||
xs.length
|
||||
) : Infinity;
|
||||
|
||||
|
||||
// liftA2 :: (a -> b -> c) -> Maybe a -> Maybe b -> Maybe c
|
||||
const liftA2 = f => a => b =>
|
||||
a.Nothing ? a : b.Nothing ? b : Just(f(a.Just)(b.Just));
|
||||
|
||||
|
||||
// lookupDict :: a -> Dict -> Maybe b
|
||||
const lookupDict = k => dct => {
|
||||
const v = dct[k];
|
||||
return undefined !== v ? (
|
||||
Just(v)
|
||||
) : Nothing();
|
||||
};
|
||||
|
||||
// map :: (a -> b) -> [a] -> [b]
|
||||
const map = f =>
|
||||
// The list obtained by applying f
|
||||
// to each element of xs.
|
||||
// (The image of xs under f).
|
||||
xs => (
|
||||
Array.isArray(xs) ? (
|
||||
xs
|
||||
) : xs.split('')
|
||||
).map(f);
|
||||
|
||||
|
||||
// pureMay :: a -> Maybe a
|
||||
const pureMay = x => Just(x);
|
||||
|
||||
// Given a type name string, returns a
|
||||
// specialised 'pure', where
|
||||
// 'pure' lifts a value into a particular functor.
|
||||
|
||||
// pureT :: String -> f a -> (a -> f a)
|
||||
const pureT = t => x =>
|
||||
'List' !== t ? (
|
||||
'Either' === t ? (
|
||||
pureLR(x)
|
||||
) : 'Maybe' === t ? (
|
||||
pureMay(x)
|
||||
) : 'Node' === t ? (
|
||||
pureTree(x)
|
||||
) : 'Tuple' === t ? (
|
||||
pureTuple(x)
|
||||
) : pureList(x)
|
||||
) : pureList(x);
|
||||
|
||||
|
||||
// pureTuple :: a -> (a, a)
|
||||
const pureTuple = x =>
|
||||
Tuple('')(x);
|
||||
|
||||
// quot :: Int -> Int -> Int
|
||||
const quot = n =>
|
||||
m => Math.floor(n / m);
|
||||
|
||||
// rem :: Int -> Int -> Int
|
||||
const rem = n => m => n % m;
|
||||
|
||||
// snd :: (a, b) -> b
|
||||
const snd = tpl => tpl[1];
|
||||
|
||||
// str :: a -> String
|
||||
const str = x =>
|
||||
x.toString();
|
||||
|
||||
// succ :: Enum a => a -> a
|
||||
const succ = x => {
|
||||
const t = typeof x;
|
||||
return 'number' !== t ? (() => {
|
||||
const [i, mx] = [x, maxBound(x)].map(fromEnum);
|
||||
return i < mx ? (
|
||||
toEnum(x)(1 + i)
|
||||
) : Error('succ :: enum out of range.')
|
||||
})() : x < Number.MAX_SAFE_INTEGER ? (
|
||||
1 + x
|
||||
) : Error('succ :: Num out of range.')
|
||||
};
|
||||
|
||||
// sum :: [Num] -> Num
|
||||
const sum = xs =>
|
||||
// The numeric sum of all values in xs.
|
||||
xs.reduce((a, x) => a + x, 0);
|
||||
|
||||
// take :: Int -> [a] -> [a]
|
||||
// take :: Int -> String -> String
|
||||
const take = n =>
|
||||
// The first n elements of a list,
|
||||
// string of characters, or stream.
|
||||
xs => 'GeneratorFunction' !== xs
|
||||
.constructor.constructor.name ? (
|
||||
xs.slice(0, n)
|
||||
) : [].concat.apply([], Array.from({
|
||||
length: n
|
||||
}, () => {
|
||||
const x = xs.next();
|
||||
return x.done ? [] : [x.value];
|
||||
}));
|
||||
|
||||
// The first argument is a sample of the type
|
||||
// allowing the function to make the right mapping
|
||||
|
||||
// toEnum :: a -> Int -> a
|
||||
const toEnum = e => x =>
|
||||
({
|
||||
'number': Number,
|
||||
'string': String.fromCodePoint,
|
||||
'boolean': Boolean,
|
||||
'object': v => e.min + v
|
||||
} [typeof e])(x);
|
||||
|
||||
|
||||
// traverse :: (Applicative f) => (a -> f b) -> [a] -> f [b]
|
||||
const traverse = f =>
|
||||
// Collected results of mapping each element
|
||||
// of a structure to an action, and evaluating
|
||||
// these actions from left to right.
|
||||
xs => 0 < xs.length ? (() => {
|
||||
const
|
||||
vLast = f(xs.slice(-1)[0]),
|
||||
t = vLast.type || 'List';
|
||||
return xs.slice(0, -1).reduceRight(
|
||||
(ys, x) => liftA2(cons)(f(x))(ys),
|
||||
liftA2(cons)(vLast)(pureT(t)([]))
|
||||
);
|
||||
})() : [
|
||||
[]
|
||||
];
|
||||
|
||||
|
||||
// uncons :: [a] -> Maybe (a, [a])
|
||||
const uncons = xs => {
|
||||
// Just a tuple of the head of xs and its tail,
|
||||
// Or Nothing if xs is an empty list.
|
||||
const lng = length(xs);
|
||||
return (0 < lng) ? (
|
||||
Infinity > lng ? (
|
||||
Just(Tuple(xs[0])(xs.slice(1))) // Finite list
|
||||
) : (() => {
|
||||
const nxt = take(1)(xs);
|
||||
return 0 < nxt.length ? (
|
||||
Just(Tuple(nxt[0])(xs))
|
||||
) : Nothing();
|
||||
})() // Lazy generator
|
||||
) : Nothing();
|
||||
};
|
||||
|
||||
|
||||
// uncurry :: (a -> b -> c) -> ((a, b) -> c)
|
||||
const uncurry = f =>
|
||||
// A function over a pair, derived
|
||||
// from a curried function.
|
||||
x => ((...args) => {
|
||||
const
|
||||
xy = 1 < args.length ? (
|
||||
args
|
||||
) : args[0];
|
||||
return f(xy[0])(xy[1]);
|
||||
})(x);
|
||||
|
||||
|
||||
// unlines :: [String] -> String
|
||||
const unlines = xs =>
|
||||
// A single string formed by the intercalation
|
||||
// of a list of strings with the newline character.
|
||||
xs.join('\n');
|
||||
|
||||
|
||||
// zip :: [a] -> [b] -> [(a, b)]
|
||||
const zip = xs =>
|
||||
// Use of `take` and `length` here allows for zipping with non-finite
|
||||
// lists - i.e. generators like cycle, repeat, iterate.
|
||||
ys => {
|
||||
const
|
||||
lng = Math.min(length(xs), length(ys)),
|
||||
vs = take(lng)(ys);
|
||||
return take(lng)(xs).map(
|
||||
(x, i) => Tuple(x)(vs[i])
|
||||
);
|
||||
};
|
||||
|
||||
// Use of `take` and `length` here allows zipping with non-finite lists
|
||||
// i.e. generators like cycle, repeat, iterate.
|
||||
|
||||
// zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
|
||||
const zipWith = f => xs => ys => {
|
||||
const lng = Math.min(length(xs), length(ys));
|
||||
return Infinity > lng ? (() => {
|
||||
const
|
||||
as = take(lng)(xs),
|
||||
bs = take(lng)(ys);
|
||||
return Array.from({
|
||||
length: lng
|
||||
}, (_, i) => f(as[i])(
|
||||
bs[i]
|
||||
));
|
||||
})() : zipWithGen(f)(xs)(ys);
|
||||
};
|
||||
|
||||
|
||||
// zipWithGen :: (a -> b -> c) ->
|
||||
// Gen [a] -> Gen [b] -> Gen [c]
|
||||
const zipWithGen = f => ga => gb => {
|
||||
function* go(ma, mb) {
|
||||
let
|
||||
a = ma,
|
||||
b = mb;
|
||||
while (!a.Nothing && !b.Nothing) {
|
||||
let
|
||||
ta = a.Just,
|
||||
tb = b.Just
|
||||
yield(f(fst(ta))(fst(tb)));
|
||||
a = uncons(snd(ta));
|
||||
b = uncons(snd(tb));
|
||||
}
|
||||
}
|
||||
return go(uncons(ga), uncons(gb));
|
||||
};
|
||||
|
||||
// MAIN ---
|
||||
return main();
|
||||
})();
|
||||
39
Task/CUSIP/Jq/cusip.jq
Normal file
39
Task/CUSIP/Jq/cusip.jq
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
def isCusip:
|
||||
length == 9 and
|
||||
explode as $s
|
||||
| {sum: 0, i: 0}
|
||||
| until(. == false or .i == 8;
|
||||
$s[.i] as $c
|
||||
| (if ($c >= 48 and $c <= 57) # '0' to '9'
|
||||
then $c - 48
|
||||
elif ($c >= 65 and $c <= 90) # 'A' to 'Z'
|
||||
then $c - 55
|
||||
elif $c == 42 # '*'
|
||||
then 36
|
||||
elif $c == 64 # '@'
|
||||
then 37
|
||||
elif $c == 35 # '#'
|
||||
then 38
|
||||
else false # return false
|
||||
end ) as $v
|
||||
| if $v == false then false
|
||||
else # check if odd as using 0-based indexing
|
||||
(if (.i%2 == 1) then 2 * $v else $v end) as $v
|
||||
| .sum += (($v/10)|floor) + $v%10
|
||||
| .i += 1
|
||||
end )
|
||||
| if . == false then false
|
||||
else $s[8] - 48 == (10 - (.sum%10)) % 10
|
||||
end;
|
||||
|
||||
def candidates: [
|
||||
"037833100",
|
||||
"17275R102",
|
||||
"38259P508",
|
||||
"594918104",
|
||||
"68389X106",
|
||||
"68389X105"
|
||||
];
|
||||
|
||||
candidates[]
|
||||
| "\(.) -> \(if isCusip then "correct" else "incorrect" end)"
|
||||
33
Task/CUSIP/Julia/cusip.julia
Normal file
33
Task/CUSIP/Julia/cusip.julia
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
module CUSIP
|
||||
|
||||
function _lastdigitcusip(input::AbstractString)
|
||||
input = uppercase(input)
|
||||
s = 0
|
||||
|
||||
for (i, c) in enumerate(input)
|
||||
if isdigit(c)
|
||||
v = Int(c) - 48
|
||||
elseif isalpha(c)
|
||||
v = Int(c) - 64 + 9
|
||||
elseif c == '*'
|
||||
v = 36
|
||||
elseif c == '@'
|
||||
v = 37
|
||||
elseif c == '#'
|
||||
v = 38
|
||||
end
|
||||
|
||||
if iseven(i); v *= 2 end
|
||||
s += div(v, 10) + rem(v, 10)
|
||||
end
|
||||
|
||||
return Char(rem(10 - rem(s, 10), 10) + 48)
|
||||
end
|
||||
|
||||
checkdigit(input::AbstractString) = input[9] == _lastdigitcusip(input[1:8])
|
||||
|
||||
end # module CUSIP
|
||||
|
||||
for code in ("037833100", "17275R102", "38259P508", "594918104", "68389X106", "68389X105")
|
||||
println("$code is ", CUSIP.checkdigit(code) ? "correct." : "not correct.")
|
||||
end
|
||||
33
Task/CUSIP/Kotlin/cusip.kotlin
Normal file
33
Task/CUSIP/Kotlin/cusip.kotlin
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// version 1.1.0
|
||||
|
||||
fun isCusip(s: String): Boolean {
|
||||
if (s.length != 9) return false
|
||||
var sum = 0
|
||||
for (i in 0..7) {
|
||||
val c = s[i]
|
||||
var v = when (c) {
|
||||
in '0'..'9' -> c.toInt() - 48
|
||||
in 'A'..'Z' -> c.toInt() - 55 // lower case letters apparently invalid
|
||||
'*' -> 36
|
||||
'@' -> 37
|
||||
'#' -> 38
|
||||
else -> return false
|
||||
}
|
||||
if (i % 2 == 1) v *= 2 // check if odd as using 0-based indexing
|
||||
sum += v / 10 + v % 10
|
||||
}
|
||||
return s[8].toInt() - 48 == (10 - (sum % 10)) % 10
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val candidates = listOf(
|
||||
"037833100",
|
||||
"17275R102",
|
||||
"38259P508",
|
||||
"594918104",
|
||||
"68389X106",
|
||||
"68389X105"
|
||||
)
|
||||
for (candidate in candidates)
|
||||
println("$candidate -> ${if(isCusip(candidate)) "correct" else "incorrect"}")
|
||||
}
|
||||
23
Task/CUSIP/Langur/cusip-1.langur
Normal file
23
Task/CUSIP/Langur/cusip-1.langur
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
val .isCusip = f(.s) {
|
||||
if not isString(.s) or len(.s) != 9 {
|
||||
return false
|
||||
}
|
||||
|
||||
val .basechars = cp2s('0'..'9') ~ cp2s('A'..'Z') ~ "*@#"
|
||||
|
||||
val .sum = for[=0] .i of 8 {
|
||||
var .v = index(s2s(.s, .i), .basechars)
|
||||
if not .v: return false
|
||||
.v = .v[1]-1
|
||||
if .i div 2: .v x= 2
|
||||
_for += .v \ 10 + .v rem 10
|
||||
}
|
||||
|
||||
.s[9]-'0' == (10-(.sum rem 10)) rem 10
|
||||
}
|
||||
|
||||
val .candidates = w/037833100 17275R102 38259P508 594918104 68389X106 68389X105/
|
||||
|
||||
for .c in .candidates {
|
||||
writeln .c, ": ", if(.isCusip(.c): "good" ; "bad")
|
||||
}
|
||||
37
Task/CUSIP/Langur/cusip-2.langur
Normal file
37
Task/CUSIP/Langur/cusip-2.langur
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
val .isCusip = f(.s) {
|
||||
if not isString(.s) or len(.s) != 9 {
|
||||
return false
|
||||
}
|
||||
|
||||
val .sum = for[=0] .i of 8 {
|
||||
val .c = .s[.i]
|
||||
var .v = 0
|
||||
|
||||
given .c {
|
||||
# for given, default op between conditions is "and"
|
||||
# for switch, default op between conditions is "or"
|
||||
case >= '0', <= '9':
|
||||
.v = .c-'0'
|
||||
|
||||
case >= 'A', <= 'Z':
|
||||
.v = .c-55 # .c-'A'+10
|
||||
|
||||
case '*': .v = 36
|
||||
case '@': .v = 37
|
||||
case '#': .v = 38
|
||||
|
||||
default: return false
|
||||
}
|
||||
|
||||
if .i div 2: .v x= 2
|
||||
_for += .v \ 10 + .v rem 10
|
||||
}
|
||||
|
||||
.s[9]-'0' == (10-(.sum rem 10)) rem 10
|
||||
}
|
||||
|
||||
val .candidates = w/037833100 17275R102 38259P508 594918104 68389X106 68389X105/
|
||||
|
||||
for .c in .candidates {
|
||||
writeln .c, ": ", if(.isCusip(.c): "good" ; "bad")
|
||||
}
|
||||
44
Task/CUSIP/Lua/cusip.lua
Normal file
44
Task/CUSIP/Lua/cusip.lua
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
function checkDigit (cusip)
|
||||
if #cusip ~= 8 then return false end
|
||||
|
||||
local sum, c, v, p = 0
|
||||
for i = 1, 8 do
|
||||
c = cusip:sub(i, i)
|
||||
if c:match("%d") then
|
||||
v = tonumber(c)
|
||||
elseif c:match("%a") then
|
||||
p = string.byte(c) - 55
|
||||
v = p + 9
|
||||
elseif c == "*" then
|
||||
v = 36
|
||||
elseif c == "@" then
|
||||
v = 37
|
||||
elseif c == "#" then
|
||||
v = 38
|
||||
end
|
||||
if i % 2 == 0 then
|
||||
v = v * 2
|
||||
end
|
||||
|
||||
sum = sum + math.floor(v / 10) + v % 10
|
||||
end
|
||||
|
||||
return tostring((10 - (sum % 10)) % 10)
|
||||
end
|
||||
|
||||
local testCases = {
|
||||
"037833100",
|
||||
"17275R102",
|
||||
"38259P508",
|
||||
"594918104",
|
||||
"68389X106",
|
||||
"68389X105"
|
||||
}
|
||||
for _, CUSIP in pairs(testCases) do
|
||||
io.write(CUSIP .. ": ")
|
||||
if checkDigit(CUSIP:sub(1, 8)) == CUSIP:sub(9, 9) then
|
||||
print("VALID")
|
||||
else
|
||||
print("INVALID")
|
||||
end
|
||||
end
|
||||
23
Task/CUSIP/Mathematica/cusip.math
Normal file
23
Task/CUSIP/Mathematica/cusip.math
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
ClearAll[Cusip]
|
||||
rules = Thread[(ToString /@ Range[0, 9]) -> Range[0, 9]]~Join~
|
||||
Thread[CharacterRange["A", "Z"] -> Range[26] + 9]~Join~
|
||||
Thread[Characters["*@#"] -> {36, 37, 38}];
|
||||
Cusip[cusip_String] := Module[{s = cusip, sum = 0, c, value, check},
|
||||
If[StringLength[s] != 9,
|
||||
Print["Cusip must be 9 characters!"];
|
||||
False
|
||||
,
|
||||
s = Characters[ToUpperCase[s]];
|
||||
Do[
|
||||
c = s[[i]];
|
||||
value = c /. rules;
|
||||
If[EvenQ[i], value *= 2];
|
||||
sum += Floor[value/10] + Mod[value, 10];
|
||||
,
|
||||
{i, 8}
|
||||
];
|
||||
check = Mod[(10 - Mod[sum, 10]), 10];
|
||||
s[[-1]] === ToString[check]
|
||||
]
|
||||
]
|
||||
Cusip /@ {"037833100", "17275R102", "38259P508", "594918104", "68389X106", "68389X105"}
|
||||
76
Task/CUSIP/Modula-2/cusip.mod2
Normal file
76
Task/CUSIP/Modula-2/cusip.mod2
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
MODULE CUSIP;
|
||||
FROM FormatString IMPORT FormatString;
|
||||
FROM Terminal IMPORT WriteString,WriteLn,ReadChar;
|
||||
|
||||
PROCEDURE WriteInt(n : INTEGER);
|
||||
VAR buf : ARRAY[0..10] OF CHAR;
|
||||
BEGIN
|
||||
FormatString("%i", buf, n);
|
||||
WriteString(buf)
|
||||
END WriteInt;
|
||||
|
||||
PROCEDURE cusipCheckDigit(cusip : ARRAY OF CHAR) : INTEGER;
|
||||
VAR
|
||||
i,v,sum : INTEGER;
|
||||
BEGIN
|
||||
i := 0;
|
||||
sum := 0;
|
||||
WHILE cusip[i] # 0C DO
|
||||
IF ('0' <= cusip[i]) AND (cusip[i] <= '9') THEN
|
||||
v := ORD(cusip[i]) - 48 (* 0 *)
|
||||
ELSIF ('A' <= cusip[i]) AND (cusip[i] <= 'Z') THEN
|
||||
v := ORD(cusip[i]) - 65 (* A *) + 10
|
||||
ELSIF cusip[i] = '*' THEN
|
||||
v := 36
|
||||
ELSIF cusip[i] = '@' THEN
|
||||
v := 37
|
||||
ELSIF cusip[i] = '#' THEN
|
||||
v := 38
|
||||
ELSE
|
||||
RETURN -1
|
||||
END;
|
||||
IF i MOD 2 = 1 THEN v := 2 * v END;
|
||||
IF i < 8 THEN
|
||||
sum := sum + (v DIV 10) + (v MOD 10);
|
||||
END;
|
||||
INC(i)
|
||||
END;
|
||||
|
||||
IF i # 9 THEN RETURN -1 END;
|
||||
RETURN (10 - (sum MOD 10)) MOD 10
|
||||
END cusipCheckDigit;
|
||||
|
||||
PROCEDURE isValidCusip(cusip : ARRAY OF CHAR) : BOOLEAN;
|
||||
VAR
|
||||
check : INTEGER;
|
||||
BEGIN
|
||||
check := cusipCheckDigit(cusip);
|
||||
IF check < 0 THEN RETURN FALSE END;
|
||||
RETURN cusip[8] = CHR(48 (* 0 *) + check)
|
||||
END isValidCusip;
|
||||
|
||||
PROCEDURE Print(cusip : ARRAY OF CHAR);
|
||||
BEGIN
|
||||
WriteString(cusip);
|
||||
IF isValidCusip(cusip) THEN
|
||||
WriteString(" : Valid")
|
||||
ELSE
|
||||
WriteString(" : Invalid")
|
||||
END;
|
||||
WriteLn
|
||||
END Print;
|
||||
|
||||
(* main *)
|
||||
BEGIN
|
||||
WriteString("CUSIP Verdict");
|
||||
WriteLn;
|
||||
|
||||
Print("037833100");
|
||||
Print("17275R102");
|
||||
Print("38259P508");
|
||||
Print("594918104");
|
||||
Print("68389X106");
|
||||
Print("68389X105");
|
||||
|
||||
ReadChar
|
||||
END CUSIP.
|
||||
38
Task/CUSIP/Nanoquery/cusip.nanoquery
Normal file
38
Task/CUSIP/Nanoquery/cusip.nanoquery
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
def cusip_checksum(cusip)
|
||||
alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
num = "0123456789"
|
||||
sum = 0
|
||||
|
||||
for i in range(1, 8)
|
||||
c = cusip[i - 1]
|
||||
v = 0
|
||||
if c in num
|
||||
v = int(c)
|
||||
else if c in alpha
|
||||
p = alpha[c] + 1
|
||||
v = p + 9
|
||||
else if c in "*@#"
|
||||
v = "*@#"[c] + 36
|
||||
end
|
||||
if (i % 2) = 0
|
||||
v *= 2
|
||||
end
|
||||
|
||||
sum += int(v / 10) + (v % 10)
|
||||
end
|
||||
|
||||
return (10 - (sum % 10)) % 10
|
||||
end
|
||||
|
||||
if main
|
||||
codes = {"037833100", "17275R102", "38259P508",\
|
||||
"594918104", "68389X106", "68389X105"}
|
||||
|
||||
for code in codes
|
||||
if int(code[len(code) - 1]) = cusip_checksum(code)
|
||||
println code + " is valid"
|
||||
else
|
||||
println code + " is invalid"
|
||||
end
|
||||
end
|
||||
end
|
||||
41
Task/CUSIP/Nim/cusip.nim
Normal file
41
Task/CUSIP/Nim/cusip.nim
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
import strutils
|
||||
|
||||
proc cusipCheck(cusip: string): bool =
|
||||
if cusip.len != 9:
|
||||
return false
|
||||
|
||||
var
|
||||
sum, v = 0
|
||||
for i, c in cusip[0 .. ^2]:
|
||||
if c.isDigit:
|
||||
v = parseInt($c)
|
||||
elif c.isUpperAscii:
|
||||
v = ord(c) - ord('A') + 10
|
||||
elif c == '*':
|
||||
v = 36
|
||||
elif c == '@':
|
||||
v = 37
|
||||
elif c == '#':
|
||||
v = 38
|
||||
|
||||
if i mod 2 == 1:
|
||||
v *= 2
|
||||
|
||||
sum += v div 10 + v mod 10
|
||||
let check = (10 - (sum mod 10)) mod 10
|
||||
return $check == $cusip[^1]
|
||||
|
||||
proc main =
|
||||
let codes = [
|
||||
"037833100",
|
||||
"17275R102",
|
||||
"38259P508",
|
||||
"594918104",
|
||||
"68389X106",
|
||||
"68389X105"
|
||||
]
|
||||
|
||||
for code in codes:
|
||||
echo code, ": ", if cusipCheck(code): "Valid" else: "Invalid"
|
||||
|
||||
main()
|
||||
58
Task/CUSIP/Objeck/cusip.objeck
Normal file
58
Task/CUSIP/Objeck/cusip.objeck
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
class Cusip {
|
||||
function : native : IsCusip(s : String) ~ Bool {
|
||||
if(s->Size() <> 9) {
|
||||
return false;
|
||||
};
|
||||
|
||||
sum := 0;
|
||||
for(i := 0; i < 7; i+=1;) {
|
||||
c := s->Get(i);
|
||||
|
||||
v : Int;
|
||||
if (c >= '0' & c <= '9') {
|
||||
v := c - 48;
|
||||
} else if (c >= 'A' & c <= 'Z') {
|
||||
v := c - 55; # lower case letters apparently invalid
|
||||
} else if (c = '*') {
|
||||
v := 36;
|
||||
} else if (c = '@') {
|
||||
v := 37;
|
||||
} else if (c = '#') {
|
||||
v := 38;
|
||||
} else {
|
||||
return false;
|
||||
};
|
||||
|
||||
# check if odd as using 0-based indexing
|
||||
if(i % 2 = 1) {
|
||||
v *= 2;
|
||||
};
|
||||
|
||||
sum += v / 10 + v % 10;
|
||||
};
|
||||
|
||||
return s->Get(8) - 48 = (10 - (sum % 10)) % 10;
|
||||
}
|
||||
|
||||
function : Main(args : String[]) ~ Nil {
|
||||
candidates := [
|
||||
"037833100",
|
||||
"17275R102",
|
||||
"38259P508",
|
||||
"594918104",
|
||||
"68389X106",
|
||||
"68389X105"
|
||||
];
|
||||
|
||||
each(i : candidates) {
|
||||
candidate := candidates[i];
|
||||
"{$candidate} => "->Print();
|
||||
if(IsCusip(candidate)) {
|
||||
"correct"->PrintLine();
|
||||
}
|
||||
else {
|
||||
"incorrect"->PrintLine();
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
39
Task/CUSIP/PHP/cusip.php
Normal file
39
Task/CUSIP/PHP/cusip.php
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
function IsCusip(string $s) {
|
||||
if (strlen($s) != 9) return false;
|
||||
$sum = 0;
|
||||
for ($i = 0; $i <= 7; $i++) {
|
||||
$c = $s[$i];
|
||||
if (ctype_digit($c)) {
|
||||
// if character is numeric, get character's numeric value
|
||||
$v = intval($c);
|
||||
} elseif (ctype_alpha($c)) {
|
||||
// if character is alphabetic, get character's ordinal position in alphabet
|
||||
$position = ord(strtoupper($c)) - ord('A') + 1;
|
||||
$v = $position + 9;
|
||||
} elseif ($c == "*") {
|
||||
$v = 36;
|
||||
} elseif ($c == "@") {
|
||||
$v = 37;
|
||||
} elseif ($c == "#") {
|
||||
$v = 38;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
// is this character position even?
|
||||
if ($i % 2 == 1) {
|
||||
$v *= 2;
|
||||
}
|
||||
// calculate the checksum digit
|
||||
$sum += floor($v / 10 ) + ( $v % 10 );
|
||||
}
|
||||
return ord($s[8]) - 48 == (10 - ($sum % 10)) % 10;
|
||||
}
|
||||
|
||||
$cusips = array("037833100",
|
||||
"17275R102",
|
||||
"38259P508",
|
||||
"594918104",
|
||||
"68389X106",
|
||||
"68389X105");
|
||||
|
||||
foreach ($cusips as $cusip) echo $cusip . " -> " . (IsCusip($cusip) ? "valid" : "invalid") . "\n";
|
||||
27
Task/CUSIP/Perl/cusip.pl
Normal file
27
Task/CUSIP/Perl/cusip.pl
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
$cv{$_} = $i++ for '0'..'9', 'A'..'Z', '*', '@', '#';
|
||||
|
||||
sub cusip_check_digit {
|
||||
my @cusip = split m{}xms, shift;
|
||||
my $sum = 0;
|
||||
|
||||
for $i (0..7) {
|
||||
return 'Invalid character found' unless $cusip[$i] =~ m{\A [[:digit:][:upper:]*@#] \z}xms;
|
||||
$v = $cv{ $cusip[$i] };
|
||||
$v *= 2 if $i%2;
|
||||
$sum += int($v/10) + $v%10;
|
||||
}
|
||||
|
||||
$check_digit = (10 - ($sum%10)) % 10;
|
||||
$check_digit == $cusip[8] ? '' : ' (incorrect)';
|
||||
}
|
||||
|
||||
my %test_data = (
|
||||
'037833100' => 'Apple Incorporated',
|
||||
'17275R102' => 'Cisco Systems',
|
||||
'38259P508' => 'Google Incorporated',
|
||||
'594918104' => 'Microsoft Corporation',
|
||||
'68389X106' => 'Oracle Corporation',
|
||||
'68389X105' => 'Oracle Corporation',
|
||||
);
|
||||
|
||||
print "$_ $test_data{$_}" . cusip_check_digit($_) . "\n" for sort keys %test_data;
|
||||
42
Task/CUSIP/Phix/cusip.phix
Normal file
42
Task/CUSIP/Phix/cusip.phix
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
(phixonline)-->
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">cch</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">CusipCheckDigit</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">cusip</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">v</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cch</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">cch</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">256</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'0'</span> <span style="color: #008080;">to</span> <span style="color: #008000;">'9'</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #000000;">cch</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #008000;">'0'</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'A'</span> <span style="color: #008080;">to</span> <span style="color: #008000;">'Z'</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #000000;">cch</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">55</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #000000;">cch</span><span style="color: #0000FF;">[</span><span style="color: #008000;">'*'</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">36</span>
|
||||
<span style="color: #000000;">cch</span><span style="color: #0000FF;">[</span><span style="color: #008000;">'@'</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">37</span>
|
||||
<span style="color: #000000;">cch</span><span style="color: #0000FF;">[</span><span style="color: #008000;">'#'</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">38</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cusip</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">9</span> <span style="color: #008080;">or</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'\0'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cusip</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">8</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #000000;">c</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">cusip</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #000000;">v</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">cch</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">v</span><span style="color: #0000FF;">=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">v</span> <span style="color: #0000FF;">*=</span> <span style="color: #000000;">2</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000000;">s</span> <span style="color: #0000FF;">+=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">v</span><span style="color: #0000FF;">/</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)+</span><span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">v</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">cusip</span><span style="color: #0000FF;">[</span><span style="color: #000000;">9</span><span style="color: #0000FF;">]=</span><span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">10</span><span style="color: #0000FF;">-</span><span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">),</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)+</span><span style="color: #008000;">'0'</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">tests</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"037833100"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- Apple Incorporated</span>
|
||||
<span style="color: #008000;">"17275R102"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- Cisco Systems</span>
|
||||
<span style="color: #008000;">"38259P508"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- Google Incorporated</span>
|
||||
<span style="color: #008000;">"594918104"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- Microsoft Corporation</span>
|
||||
<span style="color: #008000;">"68389X106"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- Oracle Corporation (incorrect)</span>
|
||||
<span style="color: #008000;">"68389X105"</span><span style="color: #0000FF;">}</span> <span style="color: #000080;font-style:italic;">-- Oracle Corporation</span>
|
||||
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #004080;">string</span> <span style="color: #000000;">ti</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s : %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">ti</span><span style="color: #0000FF;">,{</span><span style="color: #008000;">"invalid"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"valid"</span><span style="color: #0000FF;">}[</span><span style="color: #000000;">CusipCheckDigit</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ti</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]})</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<!--
|
||||
29
Task/CUSIP/PicoLisp/cusip.l
Normal file
29
Task/CUSIP/PicoLisp/cusip.l
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
(de cusip (Str)
|
||||
(let (Str (mapcar char (chop Str)) S 0)
|
||||
(for (I . C) (head 8 Str)
|
||||
(let V
|
||||
(cond
|
||||
((<= 48 C 57) (- C 48))
|
||||
((<= 65 C 90) (+ 10 (- C 65)))
|
||||
((= C 42) 36)
|
||||
((= C 64) 37)
|
||||
((= C 35) 38) )
|
||||
(or
|
||||
(bit? 1 I)
|
||||
(setq V (>> -1 V)) )
|
||||
(inc
|
||||
'S
|
||||
(+ (/ V 10) (% V 10)) ) ) )
|
||||
(=
|
||||
(- (last Str) 48)
|
||||
(% (- 10 (% S 10)) 10) ) ) )
|
||||
|
||||
(println
|
||||
(mapcar
|
||||
cusip
|
||||
(quote
|
||||
"037833100"
|
||||
"17275R102"
|
||||
"38259P508"
|
||||
"68389X106"
|
||||
"68389X105" ) ) )
|
||||
48
Task/CUSIP/PowerShell/cusip.psh
Normal file
48
Task/CUSIP/PowerShell/cusip.psh
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
function Get-CheckDigitCUSIP {
|
||||
[CmdletBinding()]
|
||||
[OutputType([int])]
|
||||
Param ( # Validate input
|
||||
[Parameter(Mandatory=$true, Position=0)]
|
||||
[ValidatePattern( '^[A-Z0-9@#*]{8}\d$' )] # @#*
|
||||
[ValidateScript({$_.Length -eq 9})]
|
||||
[string]
|
||||
$cusip
|
||||
)
|
||||
$sum = 0
|
||||
0..7 | ForEach { $c = $cusip[$_] ; $v = $null
|
||||
if ([Char]::IsDigit($c)) { $v = [char]::GetNumericValue($c) }
|
||||
if ([Char]::IsLetter($c)) { $v = [int][char]$c - [int][char]'A' +10 }
|
||||
if ($c -eq '*') { $v = 36 }
|
||||
if ($c -eq '@') { $v = 37 }
|
||||
if ($c -eq '#') { $v = 38 }
|
||||
if($_ % 2){ $v += $v }
|
||||
$sum += [int][Math]::Floor($v / 10 ) + ($v % 10)
|
||||
}
|
||||
[int]$checkDigit_calculated = ( 10 - ($sum % 10) ) % 10
|
||||
return( $checkDigit_calculated )
|
||||
}
|
||||
|
||||
function Test-IsCUSIP {
|
||||
[CmdletBinding()]
|
||||
[OutputType([bool])]
|
||||
Param (
|
||||
[Parameter(Mandatory=$true, Position=0)]
|
||||
[ValidatePattern( '^[A-Z0-9@#*]{8}\d$' )]
|
||||
[ValidateScript({$_.Length -eq 9})]
|
||||
[string]
|
||||
$cusip
|
||||
)
|
||||
[int]$checkDigit_told = $cusip[-1].ToString()
|
||||
$checkDigit_calculated = Get-CheckDigitCUSIP $cusip
|
||||
($checkDigit_calculated -eq $checkDigit_told)
|
||||
}
|
||||
|
||||
$data = @"
|
||||
037833100`tApple Incorporated
|
||||
17275R102`tCisco Systems
|
||||
38259P508`tGoogle Incorporated
|
||||
594918104`tMicrosoft Corporation
|
||||
68389X106`tOracle Corporation (incorrect)
|
||||
68389X105`tOracle Corporation
|
||||
"@ -split "`n"
|
||||
$data |%{ Test-IsCUSIP $_.Split("`t")[0] }
|
||||
42
Task/CUSIP/Python/cusip-1.py
Normal file
42
Task/CUSIP/Python/cusip-1.py
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import math
|
||||
|
||||
def cusip_check(cusip):
|
||||
if len(cusip) != 9:
|
||||
raise ValueError('CUSIP must be 9 characters')
|
||||
|
||||
cusip = cusip.upper()
|
||||
total = 0
|
||||
for i in range(8):
|
||||
c = cusip[i]
|
||||
if c.isdigit():
|
||||
v = int(c)
|
||||
elif c.isalpha():
|
||||
p = ord(c) - ord('A') + 1
|
||||
v = p + 9
|
||||
elif c == '*':
|
||||
v = 36
|
||||
elif c == '@':
|
||||
v = 37
|
||||
elif c == '#':
|
||||
v = 38
|
||||
|
||||
if i % 2 != 0:
|
||||
v *= 2
|
||||
|
||||
total += int(v / 10) + v % 10
|
||||
check = (10 - (total % 10)) % 10
|
||||
return str(check) == cusip[-1]
|
||||
|
||||
if __name__ == '__main__':
|
||||
codes = [
|
||||
'037833100',
|
||||
'17275R102',
|
||||
'38259P508',
|
||||
'594918104',
|
||||
'68389X106',
|
||||
'68389X105'
|
||||
]
|
||||
for code in codes:
|
||||
print(f'{code} -> {cusip_check(code)}')
|
||||
160
Task/CUSIP/Python/cusip-2.py
Normal file
160
Task/CUSIP/Python/cusip-2.py
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
'''CUSIP'''
|
||||
|
||||
from itertools import (cycle, islice, starmap)
|
||||
from functools import (reduce)
|
||||
from operator import (add)
|
||||
from enum import (Enum)
|
||||
|
||||
|
||||
# isCusip :: Dict -> String -> Bool
|
||||
def isCusip(dct):
|
||||
'''Test for the validity of a CUSIP string in the
|
||||
context of a supplied dictionary of char values'''
|
||||
def go(s):
|
||||
ns = [dct[c] for c in list(s) if c in dct]
|
||||
return 9 == len(ns) and (
|
||||
ns[-1] == (
|
||||
10 - (
|
||||
sum(zipWith(
|
||||
lambda f, x: add(*divmod(f(x), 10))
|
||||
)(cycle([identity, double]))(
|
||||
take(8)(ns)
|
||||
)) % 10
|
||||
)
|
||||
) % 10
|
||||
)
|
||||
return go
|
||||
|
||||
|
||||
# cusipCharDict :: () -> Dict Char Int
|
||||
def cusipCharDict():
|
||||
'''Dictionary of integer values for CUSIP characters'''
|
||||
def kv(a, ic):
|
||||
i, c = ic
|
||||
a[c] = i
|
||||
return a
|
||||
return reduce(
|
||||
kv,
|
||||
enumerate(
|
||||
enumFromTo('0')('9') + (
|
||||
enumFromTo('A')('Z') + list('*&#')
|
||||
)
|
||||
),
|
||||
{}
|
||||
)
|
||||
|
||||
|
||||
# TEST -------------------------------------------------
|
||||
# main :: IO ()
|
||||
def main():
|
||||
'''Tests'''
|
||||
|
||||
# cusipTest :: String -> Bool
|
||||
cusipTest = isCusip(cusipCharDict())
|
||||
|
||||
print(
|
||||
tabulated('Valid as CUSIP string:')(
|
||||
cusipTest
|
||||
)([
|
||||
'037833100',
|
||||
'17275R102',
|
||||
'38259P508',
|
||||
'594918104',
|
||||
'68389X106',
|
||||
'68389X105'
|
||||
])
|
||||
)
|
||||
|
||||
# GENERIC -------------------------------------------------
|
||||
|
||||
|
||||
# double :: Num -> Num
|
||||
def double(x):
|
||||
'''Wrapped here as a function for the zipWith expression'''
|
||||
return 2 * x
|
||||
|
||||
|
||||
# enumFromTo :: Enum a => a -> a -> [a]
|
||||
def enumFromTo(m):
|
||||
'''Enumeration of values [m..n]'''
|
||||
def go(x, y):
|
||||
t = type(m)
|
||||
i = fromEnum(x)
|
||||
d = 0 if t != float else (x - i)
|
||||
return list(map(
|
||||
lambda x: toEnum(t)(d + x),
|
||||
range(i, 1 + fromEnum(y))
|
||||
) if int != t else range(x, 1 + y))
|
||||
return lambda n: go(m, n)
|
||||
|
||||
|
||||
# fromEnum :: Enum a => a -> Int
|
||||
def fromEnum(x):
|
||||
'''Index integer for enumerable value.'''
|
||||
return ord(x) if str == type(x) else (
|
||||
x.value if isinstance(x, Enum) else int(x)
|
||||
)
|
||||
|
||||
|
||||
# mul :: Num -> Num -> Num
|
||||
def mul(x):
|
||||
'''Function version of (*) operator;
|
||||
a curried equivalent of operator.mul'''
|
||||
return lambda y: x * y
|
||||
|
||||
|
||||
# identity :: a -> a
|
||||
def identity(x):
|
||||
'''The identity function.
|
||||
The usual 'id' is reserved in Python.'''
|
||||
return x
|
||||
|
||||
|
||||
# tabulated :: String -> (a -> b) -> [a] -> String
|
||||
def tabulated(s):
|
||||
'''heading -> function -> input List -> tabulated output string'''
|
||||
def go(f, xs):
|
||||
def width(x):
|
||||
return len(str(x))
|
||||
w = width(max(xs, key=width))
|
||||
return s + '\n' + '\n'.join([
|
||||
str(x).rjust(w, ' ') + ' -> ' + str(f(x)) for x in xs
|
||||
])
|
||||
return lambda f: lambda xs: go(f, xs)
|
||||
|
||||
|
||||
# take :: Int -> [a] -> [a]
|
||||
# take :: Int -> String -> String
|
||||
def take(n):
|
||||
'''The prefix of xs of length n,
|
||||
or xs itself if n > length xs.'''
|
||||
return lambda xs: (
|
||||
xs[0:n]
|
||||
if isinstance(xs, list)
|
||||
else list(islice(xs, n))
|
||||
)
|
||||
|
||||
|
||||
# toEnum :: Type -> Int -> a
|
||||
def toEnum(t):
|
||||
'''Enumerable value from index integer'''
|
||||
dct = {
|
||||
int: int,
|
||||
float: float,
|
||||
str: chr,
|
||||
bool: bool
|
||||
}
|
||||
return lambda x: dct[t](x) if t in dct else t(x)
|
||||
|
||||
|
||||
# zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
|
||||
def zipWith(f):
|
||||
'''Zipping with a custom (rather than tuple) function'''
|
||||
return lambda xs: lambda ys: (
|
||||
list(starmap(f, zip(xs, ys)))
|
||||
)
|
||||
|
||||
|
||||
# MAIN ---
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
26
Task/CUSIP/Quackery/cusip.quackery
Normal file
26
Task/CUSIP/Quackery/cusip.quackery
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
[ -1 split 0 peek char 0 -
|
||||
swap 0 swap
|
||||
witheach
|
||||
[ [ dup char 0 char 9 1+ within iff
|
||||
[ char 0 - ] done
|
||||
dup char A char Z 1+ within iff
|
||||
[ char A - 10 + ] done
|
||||
dup char * = iff
|
||||
[ drop 36 ] done
|
||||
dup char @ = iff
|
||||
[ drop 37 ] done
|
||||
dup char # = iff
|
||||
[ drop 38 ] done
|
||||
$ "Unexpected character '" swap
|
||||
join $ "' in CUSIP." join fail ]
|
||||
i^ 1 & if [ 2 * ]
|
||||
10 /mod + + ]
|
||||
10 mod 10 swap - 10 mod = ] is cusip ( $ --> b )
|
||||
|
||||
[ dup echo$ cusip iff
|
||||
[ say " is correct." ]
|
||||
else [ say " is incorrect." ]
|
||||
cr ] is task ( $ --> )
|
||||
|
||||
$ "037833100 17275R102 38259P508 594918104 68389X106 68389X105"
|
||||
nest$ witheach task
|
||||
32
Task/CUSIP/REXX/cusip-1.rexx
Normal file
32
Task/CUSIP/REXX/cusip-1.rexx
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*REXX program validates that the last digit (the check digit) of a CUSIP is valid. */
|
||||
@.=
|
||||
parse arg @.1 .
|
||||
if @.1=='' | @.1=="," then do; @.1= 037833100 /* Apple Incorporated */
|
||||
@.2= 17275R102 /* Cisco Systems */
|
||||
@.3= 38259P508 /* Google Incorporated */
|
||||
@.4= 594918104 /* Microsoft Corporation */
|
||||
@.5= 68389X106 /* Oracle Corporation (incorrect)*/
|
||||
@.6= 68389X105 /* Oracle Corporation */
|
||||
end
|
||||
|
||||
do j=1 while @.j\=''; chkDig=CUSIPchk(@.j) /*calculate check digit from func*/
|
||||
OK=word("isn't is", 1 + (chkDig==right(@.j,1) ) ) /*validate check digit with func*/
|
||||
say 'CUSIP ' @.j right(OK, 6) "valid." /*display the CUSIP and validity.*/
|
||||
end /*j*/
|
||||
exit /*stick a fork in it, we're all done. */
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
CUSIPchk: procedure; arg x 9; $=0; abc= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||
do k=1 for 8
|
||||
y=substr(x, k, 1)
|
||||
select
|
||||
when datatype(y,'W') then #=y
|
||||
when datatype(y,'U') then #=pos(y, abc) + 9
|
||||
when y=='*' then #=36
|
||||
when y=='@' then #=37
|
||||
when y=='#' then #=38
|
||||
otherwise return 0 /*invalid character.*/
|
||||
end /*select*/
|
||||
if k//2==0 then #=#+# /*K even? Double it*/
|
||||
$=$ + #%10 + #//10
|
||||
end /*k*/
|
||||
return (10- $//10) // 10
|
||||
26
Task/CUSIP/REXX/cusip-2.rexx
Normal file
26
Task/CUSIP/REXX/cusip-2.rexx
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/*REXX program validates that the last digit (the check digit) of a CUSIP is valid. */
|
||||
@.=
|
||||
parse arg @.1 .
|
||||
if @.1=='' | @.1=="," then do; @.1= 037833100 /* Apple Incorporated */
|
||||
@.2= 17275R102 /* Cisco Systems */
|
||||
@.3= 38259P508 /* Google Incorporated */
|
||||
@.4= 594918104 /* Microsoft Corporation */
|
||||
@.5= 68389X106 /* Oracle Corporation (incorrect)*/
|
||||
@.6= 68389X105 /* Oracle Corporation */
|
||||
end
|
||||
|
||||
do j=1 while @.j\=''; chkDig=CUSIPchk(@.j) /*calculate check digit from func*/
|
||||
OK=word("isn't is", 1 + (chkDig==right(@.j,1) ) ) /*validate check digit with func*/
|
||||
say 'CUSIP ' @.j right(OK, 6) "valid." /*display the CUSIP and validity.*/
|
||||
end /*j*/
|
||||
exit /*stick a fork in it, we're all done. */
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
CUSIPchk: procedure; arg x 9; $=0; abc= '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ*@#'
|
||||
/* [↓] if Y isn' found, then POS returns zero.*/
|
||||
do k=1 for 8; y=substr(x,k,1) /*get a character. */
|
||||
#=pos(y, abc) - 1 /*get its position.*/
|
||||
if # == -1 then return 0 /*invalid character*/
|
||||
if k//2== 0 then #=#+# /*K even? double it*/
|
||||
$=$ + #%10 + #//10
|
||||
end /*k*/
|
||||
return (10-$//10) // 10
|
||||
37
Task/CUSIP/Racket/cusip.rkt
Normal file
37
Task/CUSIP/Racket/cusip.rkt
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
#lang racket
|
||||
(require srfi/14)
|
||||
|
||||
(define 0-char (char->integer #\0))
|
||||
(define A-char (char->integer #\A))
|
||||
|
||||
(define (cusip-value c)
|
||||
(cond
|
||||
[(char-set-contains? char-set:digit c)
|
||||
(- (char->integer c) 0-char)]
|
||||
[(char-set-contains? char-set:upper-case c)
|
||||
(+ 10 (- (char->integer c) A-char))]
|
||||
[(char=? c #\*) 36]
|
||||
[(char=? c #\@) 37]
|
||||
[(char=? c #\#) 38]))
|
||||
|
||||
(define (cusip-check-digit cusip)
|
||||
(modulo
|
||||
(- 10
|
||||
(modulo
|
||||
(for/sum
|
||||
((i (sequence-map add1 (in-range 8))) (c (in-string cusip)))
|
||||
(let* ((v (cusip-value c)) (v′ (if (even? i) (* v 2) v)))
|
||||
(+ (quotient v′ 10) (modulo v′ 10)))) 10)) 10))
|
||||
|
||||
(define (CUSIP? s)
|
||||
(char=? (string-ref s (sub1 (string-length s)))
|
||||
(integer->char (+ 0-char (cusip-check-digit s)))))
|
||||
|
||||
(module+ test
|
||||
(require rackunit)
|
||||
(check-true (CUSIP? "037833100"))
|
||||
(check-true (CUSIP? "17275R102"))
|
||||
(check-true (CUSIP? "38259P508"))
|
||||
(check-true (CUSIP? "594918104"))
|
||||
(check-false (CUSIP? "68389X106"))
|
||||
(check-true (CUSIP? "68389X105")))
|
||||
18
Task/CUSIP/Raku/cusip.raku
Normal file
18
Task/CUSIP/Raku/cusip.raku
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
sub divmod ($v, $r) { $v div $r, $v mod $r }
|
||||
my %chr = (flat 0..9, 'A'..'Z', <* @ #>) Z=> 0..*;
|
||||
|
||||
sub cuisp-check ($cuisp where *.chars == 9) {
|
||||
my ($code, $chk) = $cuisp.comb(8);
|
||||
my $sum = [+] $code.comb.kv.map: { [+] (($^k % 2 + 1) * %chr{$^v}).&divmod(10) };
|
||||
so (10 - $sum mod 10) mod 10 eq $chk;
|
||||
}
|
||||
|
||||
# TESTING
|
||||
say "$_: ", $_.&cuisp-check for <
|
||||
037833100
|
||||
17275R102
|
||||
38259P508
|
||||
594918104
|
||||
68389X106
|
||||
68389X105
|
||||
>
|
||||
57
Task/CUSIP/Ring/cusip.ring
Normal file
57
Task/CUSIP/Ring/cusip.ring
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
# Project : CUSIP
|
||||
|
||||
inputstr = list(6)
|
||||
inputstr[1] = "037833100"
|
||||
inputstr[2] = "17275R102"
|
||||
inputstr[3] = "38259P508"
|
||||
inputstr[4] = "594918104"
|
||||
inputstr[5] = "68389X106"
|
||||
inputstr[6] = "68389X105"
|
||||
for n = 1 to len(inputstr)
|
||||
cusip(inputstr[n])
|
||||
next
|
||||
|
||||
func cusip(inputstr)
|
||||
if len(inputstr) != 9
|
||||
see " length is incorrect, invalid cusip"
|
||||
return
|
||||
ok
|
||||
v = 0
|
||||
sum = 0
|
||||
for i = 1 to 8
|
||||
flag = 0
|
||||
x = ascii(inputstr[i])
|
||||
if x >= ascii("0") and x <= ascii("9")
|
||||
v = x - ascii("0")
|
||||
flag = 1
|
||||
ok
|
||||
if x >= ascii("A") and x <= ascii("Z")
|
||||
v = x - 55
|
||||
flag = 1
|
||||
ok
|
||||
if x = ascii("*")
|
||||
v= 36
|
||||
flag = 1
|
||||
ok
|
||||
if x = ascii("@")
|
||||
v = 37
|
||||
flag = 1
|
||||
ok
|
||||
if x = ascii("#")
|
||||
v = 38
|
||||
flag = 1
|
||||
ok
|
||||
if flag = 0
|
||||
see " found a invalid character, invalid cusip" + nl
|
||||
ok
|
||||
if (i % 2) = 0
|
||||
v = v * 2
|
||||
ok
|
||||
sum = sum + floor(v / 10) + v % 10
|
||||
next
|
||||
sum = (10 - (sum % 10)) % 10
|
||||
if sum = (ascii(inputstr[9]) - ascii("0"))
|
||||
see inputstr + " is valid" + nl
|
||||
else
|
||||
see inputstr + " is invalid" + nl
|
||||
ok
|
||||
38
Task/CUSIP/Ruby/cusip-1.rb
Normal file
38
Task/CUSIP/Ruby/cusip-1.rb
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
def check_cusip(cusip)
|
||||
abort('CUSIP must be 9 characters') if cusip.size != 9
|
||||
|
||||
sum = 0
|
||||
cusip.split('').each_with_index do |char, i|
|
||||
next if i == cusip.size - 1
|
||||
case
|
||||
when char.scan(/\D/).empty?
|
||||
v = char.to_i
|
||||
when char.scan(/\D/).any?
|
||||
pos = char.upcase.ord - 'A'.ord + 1
|
||||
v = pos + 9
|
||||
when char == '*'
|
||||
v = 36
|
||||
when char == '@'
|
||||
v = 37
|
||||
when char == '#'
|
||||
v = 38
|
||||
end
|
||||
|
||||
v *= 2 unless (i % 2).zero?
|
||||
sum += (v/10).to_i + (v % 10)
|
||||
end
|
||||
|
||||
check = (10 - (sum % 10)) % 10
|
||||
return 'VALID' if check.to_s == cusip.split('').last
|
||||
'INVALID'
|
||||
end
|
||||
|
||||
CUSIPs = %w[
|
||||
037833100 17275R102 38259P508 594918104 68389X106 68389X105
|
||||
]
|
||||
|
||||
CUSIPs.each do |cusip|
|
||||
puts "#{cusip}: #{check_cusip(cusip)}"
|
||||
end
|
||||
11
Task/CUSIP/Ruby/cusip-2.rb
Normal file
11
Task/CUSIP/Ruby/cusip-2.rb
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
TABLE = ("0".."9").chain("A".."Z", %w(* @ #)).zip(0..).to_h
|
||||
|
||||
def valid_CUSIP?(str)
|
||||
sum = str[0..-2].chars.each_slice(2).sum do |c1,c2|
|
||||
TABLE[c1].divmod(10).sum + (TABLE[c2]*2).divmod(10).sum
|
||||
end
|
||||
str[-1].to_i == (10 - (sum % 10)) % 10
|
||||
end
|
||||
|
||||
CUSIPs = %w(037833100 17275R102 38259P508 594918104 68389X106 68389X105)
|
||||
CUSIPs.each{|cusip| puts "#{cusip}: #{valid_CUSIP? cusip}"}
|
||||
42
Task/CUSIP/Rust/cusip.rust
Normal file
42
Task/CUSIP/Rust/cusip.rust
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
fn cusip_check(cusip: &str) -> bool {
|
||||
if cusip.len() != 9 {
|
||||
return false;
|
||||
}
|
||||
|
||||
let mut v = 0;
|
||||
let capital_cusip = cusip.to_uppercase();
|
||||
let char_indices = capital_cusip.as_str().char_indices().take(7);
|
||||
|
||||
let total = char_indices.fold(0, |total, (i, c)| {
|
||||
v = match c {
|
||||
'*' => 36,
|
||||
'@' => 37,
|
||||
'#' => 38,
|
||||
_ if c.is_digit(10) => c.to_digit(10).unwrap() as u8,
|
||||
_ if c.is_alphabetic() => (c as u8) - b'A' + 1 + 9,
|
||||
_ => v,
|
||||
};
|
||||
|
||||
if i % 2 != 0 {
|
||||
v *= 2
|
||||
}
|
||||
total + (v / 10) + v % 10
|
||||
});
|
||||
|
||||
let check = (10 - (total % 10)) % 10;
|
||||
(check.to_string().chars().nth(0).unwrap()) == cusip.chars().nth(cusip.len() - 1).unwrap()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let codes = [
|
||||
"037833100",
|
||||
"17275R102",
|
||||
"38259P508",
|
||||
"594918104",
|
||||
"68389X106",
|
||||
"68389X105",
|
||||
];
|
||||
for code in &codes {
|
||||
println!("{} -> {}", code, cusip_check(code))
|
||||
}
|
||||
}
|
||||
50
Task/CUSIP/SNOBOL4/cusip.sno
Normal file
50
Task/CUSIP/SNOBOL4/cusip.sno
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
#!/usr/local/bin/snobol4 -r
|
||||
* cusip.sno
|
||||
* -- Committee on Uniform Security Identification Procedures
|
||||
* -r : read data placed after the end label.
|
||||
* Verify check digit and size of cusip code.
|
||||
|
||||
define("cusipt()i") :(cusipt_end)
|
||||
cusipt
|
||||
chars = &digits &ucase "*@#"
|
||||
cusipt = table()
|
||||
i = 0
|
||||
cusipt_1
|
||||
chars pos(i) len(1) . c :f(return)
|
||||
cusipt[c] = i
|
||||
i = i + 1 :(cusipt_1)
|
||||
cusipt_end
|
||||
|
||||
define("check_cusip(line)c,i") :(check_cusip_end)
|
||||
check_cusip
|
||||
eq(size(line), 9) :f(freturn)
|
||||
check_cusip = 0
|
||||
i = 0
|
||||
check_cusip_1
|
||||
line pos(i) len(1) . c
|
||||
value = t[c]
|
||||
value = eq(remdr(i, 2), 1) t[c] * 2
|
||||
check_cusip = check_cusip + (value / 10) + remdr(value, 10)
|
||||
i = lt(i, 7) i + 1 :s(check_cusip_1)
|
||||
check_cusip = remdr(10 - remdr(check_cusip, 10), 10)
|
||||
eq(substr(line, 9, 1), check_cusip) :s(return)f(freturn)
|
||||
check_cusip_end
|
||||
|
||||
*** main ***
|
||||
t = cusipt()
|
||||
|
||||
read line = input :f(end)
|
||||
check_cusip(line) :f(bad_cusip)
|
||||
output = line " valid." :(read)
|
||||
bad_cusip
|
||||
output = line " not valid." :(read)
|
||||
end
|
||||
037833100
|
||||
17275R102
|
||||
38259P508
|
||||
594918104
|
||||
68389X106
|
||||
68389X105
|
||||
68389X10
|
||||
68389X1059
|
||||
68389x105
|
||||
28
Task/CUSIP/Scala/cusip.scala
Normal file
28
Task/CUSIP/Scala/cusip.scala
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
object Cusip extends App {
|
||||
|
||||
val candidates = Seq("037833100", "17275R102", "38259P508", "594918104", "68389X106", "68389X105")
|
||||
|
||||
for (candidate <- candidates)
|
||||
printf(f"$candidate%s -> ${if (isCusip(candidate)) "correct" else "incorrect"}%s%n")
|
||||
|
||||
private def isCusip(s: String): Boolean = {
|
||||
if (s.length != 9) false
|
||||
else {
|
||||
var sum = 0
|
||||
for (i <- 0 until 7) {
|
||||
val c = s(i)
|
||||
var v = 0
|
||||
if (c >= '0' && c <= '9') v = c - 48
|
||||
else if (c >= 'A' && c <= 'Z') v = c - 55 // lower case letters apparently invalid
|
||||
else if (c == '*') v = 36
|
||||
else if (c == '@') v = 37
|
||||
else if (c == '#') v = 38
|
||||
else return false
|
||||
if (i % 2 == 1) v *= 2 // check if odd as using 0-based indexing
|
||||
sum += v / 10 + v % 10
|
||||
}
|
||||
s(8) - 48 == (10 - (sum % 10)) % 10
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
67
Task/CUSIP/Swift/cusip.swift
Normal file
67
Task/CUSIP/Swift/cusip.swift
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
struct CUSIP {
|
||||
var value: String
|
||||
|
||||
private static let alphabet = Array("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
||||
|
||||
init?(value: String) {
|
||||
if value.count == 9 && String(value.last!) == CUSIP.checkDigit(cusipString: String(value.dropLast())) {
|
||||
self.value = value
|
||||
} else if value.count == 8, let checkDigit = CUSIP.checkDigit(cusipString: value) {
|
||||
self.value = value + checkDigit
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
static func checkDigit(cusipString: String) -> String? {
|
||||
guard cusipString.count == 8, cusipString.allSatisfy({ $0.isASCII }) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let sum = cusipString.uppercased().enumerated().reduce(0, {sum, pair in
|
||||
let (i, char) = pair
|
||||
var v: Int
|
||||
|
||||
switch char {
|
||||
case "*":
|
||||
v = 36
|
||||
case "@":
|
||||
v = 37
|
||||
case "#":
|
||||
v = 38
|
||||
case _ where char.isNumber:
|
||||
v = char.wholeNumberValue!
|
||||
case _:
|
||||
v = Int(char.asciiValue! - 65) + 10
|
||||
}
|
||||
|
||||
if i & 1 == 1 {
|
||||
v *= 2
|
||||
}
|
||||
|
||||
return sum + (v / 10) + (v % 10)
|
||||
})
|
||||
|
||||
return String((10 - (sum % 10)) % 10)
|
||||
}
|
||||
}
|
||||
|
||||
let testCases = [
|
||||
"037833100",
|
||||
"17275R102",
|
||||
"38259P508",
|
||||
"594918104",
|
||||
"68389X106",
|
||||
"68389X105"
|
||||
]
|
||||
|
||||
for potentialCUSIP in testCases {
|
||||
print("\(potentialCUSIP) -> ", terminator: "")
|
||||
|
||||
switch CUSIP(value: potentialCUSIP) {
|
||||
case nil:
|
||||
print("Invalid")
|
||||
case _:
|
||||
print("Valid")
|
||||
}
|
||||
}
|
||||
38
Task/CUSIP/Tcl/cusip-1.tcl
Normal file
38
Task/CUSIP/Tcl/cusip-1.tcl
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
proc ordinal-of-alpha {c} { ;# returns ordinal position of c in the alphabet (A=1, B=2...)
|
||||
lsearch {_ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z} [string toupper $c]
|
||||
}
|
||||
|
||||
proc Cusip-Check-Digit {cusip} { ;# algorithm Cusip-Check-Digit(cusip) is
|
||||
if {[string length $cusip] != 8} { ;# Input: an 8-character CUSIP
|
||||
return false
|
||||
}
|
||||
|
||||
set sum 0 ;# sum := 0
|
||||
for {set i 1} {$i <= 8} {incr i} { ;# for 1 ≤ i ≤ 8 do
|
||||
set c [string index $cusip $i-1] ;# c := the ith character of cusip
|
||||
if {[string is digit $c]} { ;# if c is a digit then
|
||||
set v $c ;# v := numeric value of the digit c
|
||||
} elseif {[string is alpha $c]} { ;# else if c is a letter then
|
||||
set p [ordinal-of-alpha $c] ;# p := ordinal position of c in the alphabet (A=1, B=2...)
|
||||
set v [expr {$p + 9}] ;# v := p + 9
|
||||
} elseif {$c eq "*"} { ;# else if c = "*" then
|
||||
set v 36 ;# v := 36
|
||||
} elseif {$c eq "@"} { ;# else if c = "@" then
|
||||
set v 37 ;# v := 37
|
||||
} elseif {$c eq "#"} { ;# else if c = "#" then
|
||||
set v 38 ;# v := 38
|
||||
} ;# end if
|
||||
if {$i % 2 == 0} { ;# if i is even then
|
||||
set v [expr {$v * 2}] ;# v := v × 2
|
||||
} ;# end if
|
||||
|
||||
incr sum [expr {$v / 10 + $v % 10}] ;# sum := sum + int ( v div 10 ) + v mod 10
|
||||
} ;# repeat
|
||||
|
||||
expr {(10 - ($sum % 10)) % 10} ;# return (10 - (sum mod 10)) mod 10
|
||||
}
|
||||
proc check-cusip {cusip} {
|
||||
set last [string index $cusip end]
|
||||
set cusip [string range $cusip 0 end-1]
|
||||
expr {$last eq [Cusip-Check-Digit $cusip]}
|
||||
}
|
||||
17
Task/CUSIP/Tcl/cusip-2.tcl
Normal file
17
Task/CUSIP/Tcl/cusip-2.tcl
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
proc check-cusip {code} {
|
||||
if {[string length $code] != 9} {
|
||||
return false
|
||||
}
|
||||
set alphabet 0123456789abcdefghijklmnopqrstuvwxyz@#
|
||||
set code [split [string tolower $code] ""]
|
||||
foreach char $code idx {1 2 3 4 5 6 7 8 9} {
|
||||
set v [string first $char $alphabet]
|
||||
if {$v == -1} {return false}
|
||||
if {$idx % 2 == 0} {
|
||||
incr v $v
|
||||
}
|
||||
set v [::tcl::mathop::+ {*}[split $v ""]]
|
||||
incr sum $v
|
||||
}
|
||||
expr {$sum % 10 == 0}
|
||||
}
|
||||
14
Task/CUSIP/Tcl/cusip-3.tcl
Normal file
14
Task/CUSIP/Tcl/cusip-3.tcl
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
proc test {} {
|
||||
foreach {cusip name} {
|
||||
037833100 "Apple Incorporated"
|
||||
17275R102 "Cisco Systems"
|
||||
38259P508 "Google Incorporated"
|
||||
594918104 "Microsoft Corporation"
|
||||
68389X106 "Oracle Corporation (incorrect)"
|
||||
68389X105 "Oracle Corporation"
|
||||
} {
|
||||
puts [format %-40s%s $name [expr {[check-cusip $cusip] ? "valid" : "invalid"}]]
|
||||
puts [format %-40s%s $name [expr {[cusip-check $cusip] ? "valid" : "invalid"}]]
|
||||
}
|
||||
}
|
||||
test
|
||||
52
Task/CUSIP/V-(Vlang)/cusip.v
Normal file
52
Task/CUSIP/V-(Vlang)/cusip.v
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
fn is_cusip(s string) bool {
|
||||
if s.len != 9 { return false }
|
||||
mut sum := 0
|
||||
for i in 0..8 {
|
||||
c := s[i]
|
||||
mut v :=0
|
||||
match true {
|
||||
c >= '0'[0] && c <= '9'[0] {
|
||||
v = c - 48
|
||||
}
|
||||
c >= 'A'[0] && c <= 'Z'[0] {
|
||||
v = c - 55
|
||||
}
|
||||
c == '*'[0] {
|
||||
v = 36
|
||||
}
|
||||
c == '@'[0] {
|
||||
v = 37
|
||||
}
|
||||
c == '#'[0] {
|
||||
v = 38
|
||||
}
|
||||
else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if i % 2 == 1 { v *= 2 } // check if odd as using 0-based indexing
|
||||
sum += v/10 + v%10
|
||||
}
|
||||
return int(s[8]) - 48 == (10 - (sum%10)) % 10
|
||||
}
|
||||
|
||||
fn main() {
|
||||
candidates := [
|
||||
"037833100",
|
||||
"17275R102",
|
||||
"38259P508",
|
||||
"594918104",
|
||||
"68389X106",
|
||||
"68389X105",
|
||||
]
|
||||
|
||||
for candidate in candidates {
|
||||
mut b :=' '
|
||||
if is_cusip(candidate) {
|
||||
b = "correct"
|
||||
} else {
|
||||
b = "incorrect"
|
||||
}
|
||||
println("$candidate -> $b")
|
||||
}
|
||||
}
|
||||
27
Task/CUSIP/VBA/cusip.vba
Normal file
27
Task/CUSIP/VBA/cusip.vba
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
Private Function Cusip_Check_Digit(s As Variant) As Integer
|
||||
Dim Sum As Integer, c As String, v As Integer
|
||||
For i = 1 To 8
|
||||
c = Mid(s, i, 1)
|
||||
If IsNumeric(c) Then
|
||||
v = Val(c)
|
||||
Else
|
||||
Select Case c
|
||||
Case "a" To "z"
|
||||
v = Asc(c) - Asc("a") + 10
|
||||
Case "A" To "Z"
|
||||
v = Asc(c) - Asc("A") + 10
|
||||
Case "*"
|
||||
v = 36
|
||||
Case "@"
|
||||
v = 37
|
||||
Case "#"
|
||||
v = 38
|
||||
Case Else
|
||||
Debug.Print "not expected"
|
||||
End Select
|
||||
End If
|
||||
If i Mod 2 = 0 Then v = v * 2
|
||||
Sum = Sum + Int(v \ 10) + v Mod 10
|
||||
Next i
|
||||
Cusip_Check_Digit = (10 - (Sum Mod 10)) Mod 10
|
||||
End Function
|
||||
48
Task/CUSIP/Visual-Basic-.NET/cusip.vb
Normal file
48
Task/CUSIP/Visual-Basic-.NET/cusip.vb
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
Module Module1
|
||||
|
||||
Function IsCUSIP(s As String) As Boolean
|
||||
If s.Length <> 9 Then
|
||||
Return False
|
||||
End If
|
||||
|
||||
Dim sum = 0
|
||||
For i = 0 To 7
|
||||
Dim c = s(i)
|
||||
|
||||
Dim v As Integer
|
||||
If "0" <= c AndAlso c <= "9" Then
|
||||
v = Asc(c) - 48
|
||||
ElseIf "A" <= c AndAlso c <= "Z" Then
|
||||
v = Asc(c) - 55 ' Lower case letters are apparently invalid
|
||||
ElseIf c = "*" Then
|
||||
v = 36
|
||||
ElseIf c = "#" Then
|
||||
v = 38
|
||||
Else
|
||||
Return False
|
||||
End If
|
||||
|
||||
If i Mod 2 = 1 Then
|
||||
v *= 2 ' check if odd as using 0-based indexing
|
||||
End If
|
||||
sum += v \ 10 + v Mod 10
|
||||
Next
|
||||
Return Asc(s(8)) - 48 = (10 - (sum Mod 10)) Mod 10
|
||||
End Function
|
||||
|
||||
Sub Main()
|
||||
Dim candidates As New List(Of String) From {
|
||||
"037833100",
|
||||
"17275R102",
|
||||
"38259P508",
|
||||
"594918104",
|
||||
"68389X106",
|
||||
"68389X105"
|
||||
}
|
||||
|
||||
For Each candidate In candidates
|
||||
Console.WriteLine("{0} -> {1}", candidate, If(IsCUSIP(candidate), "correct", "incorrect"))
|
||||
Next
|
||||
End Sub
|
||||
|
||||
End Module
|
||||
37
Task/CUSIP/Wren/cusip.wren
Normal file
37
Task/CUSIP/Wren/cusip.wren
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
var isCusip = Fn.new { |s|
|
||||
if (s.count != 9) return false
|
||||
var sum = 0
|
||||
for (i in 0..7) {
|
||||
var c = s[i].bytes[0]
|
||||
var v
|
||||
if (c >= 48 && c <= 57) { // '0' to '9'
|
||||
v = c - 48
|
||||
} else if (c >= 65 && c <= 90) { // 'A' to 'Z'
|
||||
v = c - 55
|
||||
} else if (s[i] == "*") {
|
||||
v = 36
|
||||
} else if (s[i] == "@") {
|
||||
v = 37
|
||||
} else if (s[i] == "#") {
|
||||
v = 38
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
if (i%2 == 1) v = v * 2 // check if odd as using 0-based indexing
|
||||
sum = sum + (v/10).floor + v%10
|
||||
}
|
||||
return s[8].bytes[0] - 48 == (10 - (sum%10)) % 10
|
||||
}
|
||||
|
||||
var candidates = [
|
||||
"037833100",
|
||||
"17275R102",
|
||||
"38259P508",
|
||||
"594918104",
|
||||
"68389X106",
|
||||
"68389X105"
|
||||
]
|
||||
for (candidate in candidates) {
|
||||
var b = (isCusip.call(candidate)) ? "correct" : "incorrect"
|
||||
System.print("%(candidate) -> %(b)")
|
||||
}
|
||||
39
Task/CUSIP/XPL0/cusip.xpl0
Normal file
39
Task/CUSIP/XPL0/cusip.xpl0
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
string 0; \use zero-terminated strings
|
||||
|
||||
func Valid(Cusip); \Return 'true' if valid CUSIP code
|
||||
char Cusip;
|
||||
int Sum, I, C, V;
|
||||
[Sum:= 0;
|
||||
for I:= 0 to 8-1 do
|
||||
[C:= Cusip(I);
|
||||
ChOut(0, C);
|
||||
case of
|
||||
C>=^0 & C<=^9: V:= C-^0;
|
||||
C>=^A & C<=^Z: V:= C-^A+10;
|
||||
C=^*: V:=36;
|
||||
C=^@: V:=37;
|
||||
C=^#: V:=38
|
||||
other V:= -1;
|
||||
if I&1 then V:= V*2;
|
||||
Sum:= Sum + V/10 + rem(0);
|
||||
];
|
||||
C:= Cusip(I);
|
||||
ChOut(0, C);
|
||||
V:= rem( (10-rem(Sum/10)) / 10 );
|
||||
return V = C-^0;
|
||||
];
|
||||
|
||||
int Cusip, N;
|
||||
[Cusip:= ["037833100",
|
||||
"17275R102",
|
||||
"38259P508",
|
||||
"594918104",
|
||||
"68389X106",
|
||||
"68389X105"];
|
||||
for N:= 0 to 6-1 do
|
||||
[Text(0, if Valid(Cusip(N))
|
||||
then " is valid"
|
||||
else " is invalid");
|
||||
CrLf(0);
|
||||
];
|
||||
]
|
||||
47
Task/CUSIP/Yabasic/cusip.basic
Normal file
47
Task/CUSIP/Yabasic/cusip.basic
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
sub cusip(inputStr$)
|
||||
local i, v, sum, x$
|
||||
|
||||
Print inputStr$;
|
||||
If Len(inputStr$) <> 9 Print " length is incorrect, invalid cusip" : return
|
||||
|
||||
For i = 1 To 8
|
||||
x$ = mid$(inputStr$, i, 1)
|
||||
switch x$
|
||||
Case "*": v = 36 : break
|
||||
Case "@": v = 37 : break
|
||||
Case "#": v = 38 : break
|
||||
default:
|
||||
if x$ >= "A" and x$ <= "Z" then
|
||||
v = asc(x$) - Asc("A") + 10
|
||||
elsif x$ >= "0" and x$ <= "9" then
|
||||
v = asc(x$) - asc("0")
|
||||
else
|
||||
Print " found a invalid character, invalid cusip"
|
||||
return
|
||||
end if
|
||||
End switch
|
||||
|
||||
If and(i, 1) = 0 v = v * 2
|
||||
sum = sum + int(v / 10) + mod(v, 10)
|
||||
Next
|
||||
|
||||
sum = mod(10 - mod(sum, 10), 10)
|
||||
If sum = asc(mid$(inputStr$, 9, 1)) - Asc("0") Then
|
||||
Print " is valid"
|
||||
Else
|
||||
Print " is invalid"
|
||||
End If
|
||||
|
||||
End Sub
|
||||
|
||||
// ------=< MAIN >=------
|
||||
|
||||
Data "037833100", "17275R102", "38259P508"
|
||||
Data "594918104", "68389X106", "68389X105", ""
|
||||
|
||||
Print
|
||||
do
|
||||
Read inputStr$
|
||||
if inputStr$ = "" break
|
||||
cusip(inputStr$)
|
||||
loop
|
||||
49
Task/CUSIP/Zig/cusip.zig
Normal file
49
Task/CUSIP/Zig/cusip.zig
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
const std = @import("std");
|
||||
const print = std.debug.print;
|
||||
|
||||
pub fn CusipCheckDigit(cusip: *const [9:0]u8) bool {
|
||||
var i: usize = 0;
|
||||
var sum: i32 = 0;
|
||||
while (i < 8) {
|
||||
const c = cusip[i];
|
||||
var v: i32 = undefined;
|
||||
if (c <= '9' and c >= '0') {
|
||||
v = c - 48;
|
||||
}
|
||||
else if (c <= 'Z' and c >= 'A') {
|
||||
v = c - 55;
|
||||
}
|
||||
else if (c == '*') {
|
||||
v = 36;
|
||||
}
|
||||
else if (c == '@') {
|
||||
v = 37;
|
||||
}
|
||||
else if (c == '#') {
|
||||
v = 38;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
if (i % 2 == 1) {
|
||||
v *= 2;
|
||||
}
|
||||
sum = sum + @divFloor(v, 10) + @mod(v, 10);
|
||||
i += 1;
|
||||
}
|
||||
return (cusip[8] - 48 == @mod((10 - @mod(sum, 10)), 10));
|
||||
}
|
||||
|
||||
pub fn main() void {
|
||||
const cusips = [_]*const [9:0]u8 {
|
||||
"037833100",
|
||||
"17275R102",
|
||||
"38259P508",
|
||||
"594918104",
|
||||
"68389X106",
|
||||
"68389X105"
|
||||
};
|
||||
for (cusips) |cusip| {
|
||||
print("{s} -> {}\n", .{cusip, CusipCheckDigit(cusip)});
|
||||
}
|
||||
}
|
||||
8
Task/CUSIP/Zkl/cusip-1.zkl
Normal file
8
Task/CUSIP/Zkl/cusip-1.zkl
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fcn cusipCheckDigit(cusip){
|
||||
var [const] vs=[0..9].chain(["A".."Z"],T("*","@","#")).pump(String);
|
||||
try{
|
||||
sum:=Walker.cycle(1,2).zipWith(fcn(n,c){ v:=vs.index(c)*n; v/10 + v%10 },
|
||||
cusip[0,8]).reduce('+);
|
||||
((10 - sum%10)%10 == cusip[8].toInt()) and cusip.len()==9
|
||||
}catch{ False }
|
||||
}
|
||||
4
Task/CUSIP/Zkl/cusip-2.zkl
Normal file
4
Task/CUSIP/Zkl/cusip-2.zkl
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
foreach cusip in (T("037833100", "17275R102",
|
||||
"38259P508", "594918104", "68389X106", "68389X105")){
|
||||
println(cusip,": ",cusipCheckDigit(cusip));
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue