CUSIP: Difference between revisions
→{{header|langur}}
Alextretyak (talk | contribs) (Added 11l) |
Langurmonkey (talk | contribs) |
||
(29 intermediate revisions by 20 users not shown) | |||
Line 17:
;Example pseudo-code below.
<syntaxhighlight lang=text>algorithm Cusip-Check-Digit(cusip) is
Input: an 8-character CUSIP
Line 43:
return (10 - (sum mod 10)) mod 10
end function</
;See related tasks:
Line 53:
{{trans|Python}}
<
I cusip.len != 9
X.throw ValueError(‘CUSIP must be 9 characters’)
cusip = cusip.uppercase()
Line 88:
‘68389X105’]
L(code) codes
print(code‘: ’(I cusip_check(code) {‘valid’} E ‘invalid’))</
{{out}}
Line 101:
=={{header|360 Assembly}}==
<
CUSIP CSECT
USING CUSIP,R13 base register
Line 181:
PG DC CL80'CUSIP ......... is... valid'
YREGS
END CUSIP</
{{out}}
<pre>
Line 190:
CUSIP 68389X106 isn't valid
CUSIP 68389X105 is valid
</pre>
=={{header|Action!}}==
{{libheader|Action! Tool Kit}}
<syntaxhighlight lang=Action!>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</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/CUSIP.png Screenshot from Atari 8-bit computer]
<pre>
037833100 is valid
17275R102 is valid
38259P508 is valid
594918104 is valid
68389X106 is invalid
68389X105 is valid
</pre>
=={{header|Ada}}==
<
procedure Cusip_Test is
Line 246 ⟶ 320:
end if;
end loop;
end Cusip_Test;</
{{Out}}
<pre>037833100: valid
Line 257 ⟶ 331:
=={{header|ALGOL 68}}==
<
# returns TRUE if cusip is a valid CUSIP code #
OP ISCUSIP = ( STRING cusip )BOOL:
Line 305 ⟶ 379:
test cusip( "68389X106" );
test cusip( "68389X105" )
END</
{{out}}
<pre>
Line 318 ⟶ 392:
=={{header|ALGOL W}}==
Based on Algol 68
<
logical procedure isCusip ( string(9) value cusip ) ;
begin
Line 352 ⟶ 426:
testCusip( "68389X105" )
end testCases
end.</
{{out}}
<pre>
Line 364 ⟶ 438:
=={{header|AppleScript}}==
<
use framework "Foundation"
use scripting additions
Line 643 ⟶ 717:
return lst
end tell
end zipWith</
{{Out}}
<pre>037833100 -> true
Line 651 ⟶ 725:
68389X106 -> false
68389X105 -> true</pre>
=={{header|Arturo}}==
{{trans|Ruby}}
<syntaxhighlight lang=rebol>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"]
]</syntaxhighlight>
{{out}}
<pre>037833100 => VALID
17275R102 => VALID
38259P508 => VALID
594918104 => VALID
68389X106 => INVALID
68389X105 => VALID</pre>
=={{header|AutoHotkey}}==
<
sum := 0, i := 1, x := StrSplit(cusip)
while (i <= 8) {
Line 673 ⟶ 786:
}
return (Mod(10 - Mod(sum, 10), 10) = x[9])
}</
Examples:<
(
037833100
Line 687 ⟶ 800:
loop, Parse, data, `n, `r
output .= A_LoopField "`t" Cusip_Check_Digit(A_LoopField) "`n"
MsgBox % output</
{{out}}
<pre>Cusip Valid
Line 698 ⟶ 811:
=={{header|AWK}}==
<
# syntax: GAWK -f CUSIP.AWK
BEGIN {
Line 740 ⟶ 853:
return(substr(n,9,1) == x ? 1 : 0)
}
</syntaxhighlight>
{{out}}
<pre>
Line 750 ⟶ 863:
68389X105 1
</pre>
=={{header|BASIC}}==
==={{header|FreeBASIC}}===
<syntaxhighlight lang=freebasic>' 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</syntaxhighlight>
{{out}}
<pre>037833100 is valid
17275R102 is valid
38259P508 is valid
594918104 is valid
68389X106 is invalid
68389X105 is valid</pre>
==={{header|VBA}}===
<syntaxhighlight lang=vb>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</syntaxhighlight>{{out}}
<pre>037833100 is valid
17275R102 is valid
38259P508 is valid
594918104 is valid
68389X106 not valid
68389X105 is valid</pre>
==={{header|Visual Basic .NET}}===
{{trans|C#}}
<syntaxhighlight lang=vbnet>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</syntaxhighlight>
{{out}}
<pre>037833100 -> correct
17275R102 -> correct
38259P508 -> correct
594918104 -> correct
68389X106 -> incorrect
68389X105 -> correct</pre>
==={{header|Yabasic}}===
{{trans|FreeBASIC}}
<syntaxhighlight lang=Yabasic>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
</syntaxhighlight>
=={{header|BCPL}}==
<
let validcusip(c) = valof
Line 786 ⟶ 1,116:
show("68389X106")
show("68389X105")
$)</
{{out}}
<pre>037833100: valid
Line 797 ⟶ 1,127:
=={{header|C}}==
Reads CUSIP strings from a file and prints results to console, usage printed on incorrect invocation.
<syntaxhighlight lang=C>
#include<stdlib.h>
#include<stdio.h>
Line 851 ⟶ 1,181:
return 0;
}
</syntaxhighlight>
Input file :
<pre>
Line 877 ⟶ 1,207:
=={{header|C sharp|C#}}==
{{trans|Java}}
<
using System.Collections.Generic;
Line 893 ⟶ 1,223:
}
else if (c >= 'A' && c <= 'Z') {
v = c -
}
else if (c == '*') {
Line 924 ⟶ 1,254:
}
}
}</
{{out}}
<pre>037833100 -> correct
Line 935 ⟶ 1,265:
=={{header|C++}}==
{{trans|C#}}
<
#include <vector>
Line 949 ⟶ 1,279:
v = c - '0';
} else if ('A' <= c && c <= 'Z') {
v = c - '
} else if (c = '*') {
v = 36;
} else if (c = '@') {
v = 37;
} else if (c = '#') {
v = 38;
Line 983 ⟶ 1,315:
return 0;
}</
{{out}}
<pre>037833100 -> correct
Line 994 ⟶ 1,326:
=={{header|Caché ObjectScript}}==
<
{
Line 1,012 ⟶ 1,344:
}
}</
{{out|Examples}}
<pre>USER>For { Read s Quit:s="" Write ": "_##class(Utils.Check).CUSIP(s), ! }
Line 1,025 ⟶ 1,357:
=={{header|Clojure}}==
<
(defn- char->value
"convert the given char c to a value used to calculate the cusip check sum"
Line 1,032 ⟶ 1,364:
(cond
(and (>= int-char (int \0)) (<= int-char (int \9))) (- int-char 48)
(and (>= int-char (int \A)) (<= int-char (int \Z))) (- int-char
(= c \*) 36
(= c \@) 37
Line 1,069 ⟶ 1,401:
"show some nice output for the Rosetta Wiki"
[]
(doseq [cusip ["037833100" "17275R102" "38259P508" "594918104" "68389X106" "68389X105" "EXTRACRD8"
"
(println cusip (if (is-valid-cusip9? cusip) "valid" "invalid"))))
</syntaxhighlight>
{{out}}
Line 1,083 ⟶ 1,415:
68389X106 invalid
68389X105 valid
EXTRACRD8
EXTRACRD9 valid
BADCUSIP! invalid
683&9X106 invalid
Line 1,089 ⟶ 1,422:
683$9X106 invalid
68389}105 invalid
87264ABE4 valid
</pre>
=={{header|CLU}}==
<syntaxhighlight lang=clu>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</syntaxhighlight>
{{out}}
<pre>037833100: valid
17275R102: valid
38259P508: valid
594918104: valid
68389X106: invalid
68389X105: valid</pre>
=={{header|Common Lisp}}==
<
(cond ((digit-char-p c 36))
((char= c #\*) 36)
Line 1,114 ⟶ 1,490:
(defun main ()
(dolist (cusip '("037833100" "17275R102" "38259P508" "594918104" "68389X106" "68389X105"))
(format t "~A: ~A~%" cusip (cusip-p cusip))))</
{{out}}
<pre>037833100: T
Line 1,124 ⟶ 1,500:
=={{header|D}}==
<
void main(string[] args) {
Line 1,222 ⟶ 1,598:
}
/// Invoke with `cusip 037833100 17275R102 38259P508 594918104 68389X106 68389X105`</
{{out}}
Line 1,232 ⟶ 1,608:
68389X106 : Invalid
68389X105 : Valid</pre>
=={{header|Delphi}}==
{{works with|Delphi|6.0}}
{{libheader|SysUtils,StdCtrls}}
Using sets to simplify string parsing
<syntaxhighlight lang="Delphi">
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;
</syntaxhighlight>
{{out}}
<pre>
037833100 Apple Incorporated: Valid
17275R102 Cisco Systems: Valid
38259P508 Google Incorporated: Valid
594918104 Microsoft Corporation: Valid
68389X106 Oracle Corporation: Invalid
68389X105 Oracle Corporation: Valid
</pre>
=={{header|Dyalect}}==
Line 1,237 ⟶ 1,681:
{{trans|Go}}
<
if s.
var sum = 0
for i in 0..7 {
Line 1,244 ⟶ 1,688:
var v =
match c {
'0'..'9' => c.
'A'..'Z' => c.
'*' => 36,
'@' => 37,
Line 1,254 ⟶ 1,698:
sum += v / 10 + v % 10
}
s[8].
}
Line 1,274 ⟶ 1,718:
}
print("\(candidate) -> \(b)")
}</
{{out}}
Line 1,284 ⟶ 1,728:
68389X106 -> incorrect
68389X105 -> correct</pre>
=={{header|EasyLang}}==
<syntaxhighlight lang=easylang>
func check inp$ .
for i = 1 to 8
c = strcode substr inp$ i 1
if c >= 48 and c <= 57
v = c - 48
elif c >= 65 and c <= 91
v = c - 64 + 9
elif c = 42
v = 36
elif c = 64
v = 37
elif c = 35
v = 38
.
if i mod 2 = 0
v *= 2
.
sum += v div 10 + v mod 10
.
return if (10 - (sum mod 10)) mod 10 = number substr inp$ 9 1
.
for s$ in [ "037833100" "17275R102" "38259P508" "594918104" "68389X106" "68389X105" ]
write s$ & " is "
if check s$ = 1
print "valid"
else
print "invalid"
.
.
</syntaxhighlight>
=={{header|Excel}}==
Line 1,292 ⟶ 1,770:
(See [https://www.microsoft.com/en-us/research/blog/lambda-the-ultimatae-excel-worksheet-function/ LAMBDA: The ultimate Excel worksheet function])
<
LET(
ns, VLOOKUP(
Line 1,330 ⟶ 1,808:
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}</
and also assuming the following generic bindings in the Name Manager for the WorkBook:
<
=LAMBDA(s,
MID(
Line 1,364 ⟶ 1,842:
COLUMNS(xs)
)
)</
{{Out}}
Line 1,406 ⟶ 1,884:
=={{header|F_Sharp|F#}}==
<
// 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"))
</syntaxhighlight>
{{out}}
<pre>
Line 1,423 ⟶ 1,901:
</pre>
=={{header|Factor}}==
<
math.parser qw regexp sequences unicode ;
IN: rosetta-code.cusip
Line 1,440 ⟶ 1,918:
qw{ 037833100 17275R102 38259P508 594918104 68389X106 68389X105 }
[ dup cusip? "correct" "incorrect" ? "%s -> %s\n" printf ] each</
{{out}}
<pre>
Line 1,456 ⟶ 1,934:
The source does not bother with the MODULE protocol of F90 and later, and so the type of function CUSIPCHECK must be declared in all routines wishing to invoke it. However, the F90 feature of having the END statement of a subroutine or function give its name is to valuable to ignore. The function returns a character code rather than an integer, since the presumption is that it is to be compared to the check character of the code being inspected, which is known as a character not an integer. This means some blather when extracting the eight characters to be presented to CUSIPCHECK and comparing the result to the ninth character, but the test can be done in one expression.
There is no checking that only valid characters are presented, nor that eight-character codes only are offered, though the compiler might complain if the function were to be invoked with a text literal of the wrong size. In the absence of such checks, there need be no added complications to support a scheme for reporting such errors. <
Committee on Uniform Security Identification Purposes, of the American (i.e. USA) Bankers' Association.
CHARACTER*8 TEXT !Specifically, an eight-symbol code.
Line 1,489 ⟶ 1,967:
END DO
END</
Output: standard output is to I/O unit 6, and free-format (the *) will suffice for this. Each line output starts with a space (in case it is to go to a lineprinter, with carriage control), which is convenient for layout here.
Line 1,501 ⟶ 1,979:
This would have worked first time, except that a fymgre frmble caused the omission of the digit 2 from the text of VALID. The benefits of checking checksums reach to unexpected places!
=={{header|FutureBasic}}==
<syntaxhighlight lang="futurebasic">
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
</syntaxhighlight>
{{output}}
<pre>
0378331009: Invalid length
037833100: Valid
17275R102: Valid
38259P508: Valid
594918104: Valid
68389X106: Invalid
68389X105: Valid
683&9X105: Invalid character: &
</pre>
=={{header|Go}}==
<
import "fmt"
Line 1,588 ⟶ 2,059:
v = int(c) - 48
case c >= 'A' && c <= 'Z':
v = int(c) -
case c == '*':
v = 36
Line 1,624 ⟶ 2,095:
}
}
</syntaxhighlight>
{{out}}
Line 1,638 ⟶ 2,109:
=={{header|Groovy}}==
{{trans|Java}}
<
private static Boolean isCusip(String s) {
if (s.length() != 9) return false
Line 1,649 ⟶ 2,120:
v = c - 48
} else if (c >= ('A' as char) && c <= ('Z' as char)) {
v = c -
} else if (c == '*' as char) {
v = 36
Line 1,677 ⟶ 2,148:
}
}
}</
{{out}}
<pre>037833100 -> correct
Line 1,687 ⟶ 2,158:
=={{header|Haskell}}==
<
data Result = Valid | BadCheck | TooLong | TooShort | InvalidContent deriving Show
Line 1,730 ⟶ 2,201:
]
main = mapM_ putStrLn (fmap (\s -> s ++ ": " ++ show (checkCUSIP s)) testData)</
{{out}}
Line 1,741 ⟶ 2,212:
</pre>
Or,
<
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 $
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",
]</
{{Out}}
<pre>("037833100",True)
Line 1,777 ⟶ 2,259:
=={{header|Icon}} and {{header|Unicon}}==
<
procedure main()
Line 1,816 ⟶ 2,298:
t[chars[n]] := (n - 1)
return t
end</
{{out}}<pre>037833100 : valid.
Line 1,828 ⟶ 2,310:
=={{header|J}}==
One-liner:
<
ccd '68389X10'
5</
More verbose version that checks for correct input:
<
assert. 8 = $ y NB. Only accept an 8-element long list
assert. */ y e. '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ*@#' NB. Only accept characters from the list of 38
Line 1,842 ⟶ 2,324:
)
addCUSIPcheckdigit =: , CUSIPcheckdigit
verifyCUSIPcheckdigit =: {: = CUSIPcheckdigit@}:</
Examples:
<
68389X105
verifyCUSIPcheckdigit '68389X106'
Line 1,860 ⟶ 2,342:
│68389X106│0│
│68389X105│1│
└─────────┴─┘</
=={{header|Java}}==
{{trans|Kotlin}}
Uses Java 9
<
public class Cusip {
Line 1,878 ⟶ 2,360:
v = c - 48;
} else if (c >= 'A' && c <= 'Z') {
v = c -
} else if (c == '*') {
v = 36;
Line 1,896 ⟶ 2,378:
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) {
Line 1,907 ⟶ 2,385:
}
}
}</
{{out}}
<pre>037833100 -> correct
Line 1,915 ⟶ 2,393:
68389X106 -> incorrect
68389X105 -> correct
EXTRACRD8 -> incorrect
EXTRACRD9 -> correct
BADCUSIP! -> incorrect
683&9X106 -> incorrect
68389x105 -> incorrect
683$9X106 -> incorrect
68389}105 -> incorrect
87264ABE4 -> correct
</pre>
=={{header|JavaScript}}==
<
'use strict';
Line 2,346 ⟶ 2,832:
// MAIN ---
return main();
})();</
{{Out}}
<pre>037833100 -> true
Line 2,354 ⟶ 2,840:
68389X106 -> false
68389X105 -> true</pre>
=={{header|jq}}==
''Adapted from [[#Wren|Wren]]''
{{works with|jq}}
'''Also works with gojq, the Go implementation of jq, and with jackson-jq and fq.'''
<syntaxhighlight lang=jq>
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)"
</syntaxhighlight>
{{output}}
<pre>
037833100 -> correct
17275R102 -> correct
38259P508 -> correct
594918104 -> correct
68389X106 -> incorrect
68389X105 -> correct
</pre>
=={{header|Julia}}==
{{works with|Julia|0.6}}
<
function _lastdigitcusip(input::AbstractString)
Line 2,390 ⟶ 2,931:
for code in ("037833100", "17275R102", "38259P508", "594918104", "68389X106", "68389X105")
println("$code is ", CUSIP.checkdigit(code) ? "correct." : "not correct.")
end</
{{out}}
Line 2,401 ⟶ 2,942:
=={{header|Kotlin}}==
<
fun isCusip(s: String): Boolean {
Line 2,410 ⟶ 2,951:
var v = when (c) {
in '0'..'9' -> c.toInt() - 48
in 'A'..'Z' -> c.toInt() -
'*' -> 36
'@' -> 37
Line 2,433 ⟶ 2,974:
for (candidate in candidates)
println("$candidate -> ${if(isCusip(candidate)) "correct" else "incorrect"}")
}</
{{out}}
Line 2,447 ⟶ 2,988:
=={{header|langur}}==
If we don't strictly follow the pseudo-code, we can do this.
<syntaxhighlight lang=langur>val .isCusip = fn(.s) {
if .s is not string or len(.s) != 9 {
return false
}
val .basechars =
val .sum = for[=0] .i of 8 {
Line 2,460 ⟶ 2,999:
if not .v: return false
.v = .v[1]-1
if .i div 2: .v
_for += .v \ 10 + .v rem 10
}
Line 2,467 ⟶ 3,006:
}
val .candidates =
for .c in .candidates {
writeln .c, ": ", if(.isCusip(.c): "good" ; "bad")
}</
Following the pseudo-code would look more like the following.
{{trans|Go}}
<
if
return false
}
Line 2,486 ⟶ 3,023:
var .v = 0
case >= '0', <= '9':
.v = .c-'0'
Line 2,502 ⟶ 3,037:
}
if .i div 2: .v
_for += .v \ 10 + .v rem 10
}
Line 2,513 ⟶ 3,048:
for .c in .candidates {
writeln .c, ": ", if(.isCusip(.c): "good" ; "bad")
}</
{{out}}
Line 2,525 ⟶ 3,060:
=={{header|Lua}}==
The checkDigit function is a line-for-line translation of the pseudo-code algorithm.
<
if #cusip ~= 8 then return false end
Line 2,534 ⟶ 3,069:
v = tonumber(c)
elseif c:match("%a") then
p = string.byte(c) -
v = p + 9
elseif c == "*" then
Line 2,568 ⟶ 3,103:
print("INVALID")
end
end</
{{out}}
<pre>037833100: VALID
Line 2,578 ⟶ 3,113:
=={{header|Mathematica}} / {{header|Wolfram Language}}==
<
rules = Thread[(ToString /@ Range[0, 9]) -> Range[0, 9]]~Join~
Thread[CharacterRange["A", "Z"] -> Range[26] + 9]~Join~
Line 2,600 ⟶ 3,135:
]
]
Cusip /@ {"037833100", "17275R102", "38259P508", "594918104", "68389X106", "68389X105"}</
{{out}}
<pre>{True, True, True, True, False, True}</pre>
=={{header|MiniScript}}==
<syntaxhighlight lang="miniscript">isCusip = function(s)
if s.len != 9 then return false
sum = 0
for i in range(0, 7)
c = s[i]
v = 0
if c >= "0" and c <= "9" then
v = code(c) - 48
else if c >= "A" and c <= "Z" then
v = code(c) - 55
else if c == "*" then
v = 36
else if c == "@" then
v = 37
else if c == "#" then
v = 38
else
return false
end if
if i%2 == 1 then v *= 2 // check if odd as using 0-based indexing
sum += floor(v/10) + v%10
end for
return code(s[8]) - 48 == (10 - (sum%10)) % 10
end function
candidates = [
"037833100", "17275R102", "38259P508",
"594918104", "68389X106", "68389X105",
]
for candidate in candidates
s = "valid"
if not isCusip(candidate) then s = "invalid"
print candidate + " -> " + s
end for</syntaxhighlight>
{{out}}
<pre>037833100 -> valid
17275R102 -> valid
38259P508 -> valid
594918104 -> valid
68389X106 -> invalid
68389X105 -> valid
</pre>
=={{header|Modula-2}}==
<
FROM FormatString IMPORT FormatString;
FROM Terminal IMPORT WriteString,WriteLn,ReadChar;
Line 2,680 ⟶ 3,260:
ReadChar
END CUSIP.</
{{out}}
<pre>CUSIP Verdict
Line 2,691 ⟶ 3,271:
=={{header|Nanoquery}}==
<
alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
num = "0123456789"
Line 2,728 ⟶ 3,308:
end
end
end</
{{out}}
Line 2,739 ⟶ 3,319:
=={{header|Nim}}==
<
proc cusipCheck(cusip: string): bool =
Line 2,779 ⟶ 3,359:
echo code, ": ", if cusipCheck(code): "Valid" else: "Invalid"
main()</
{{out}}
Line 2,792 ⟶ 3,372:
=={{header|Objeck}}==
{{trans|Kotlin}}
<
function : native : IsCusip(s : String) ~ Bool {
if(s->Size() <> 9) {
Line 2,806 ⟶ 3,386:
v := c - 48;
} else if (c >= 'A' & c <= 'Z') {
v := c -
} else if (c = '*') {
v := 36;
Line 2,849 ⟶ 3,429:
};
}
}</
Output:
Line 2,863 ⟶ 3,443:
=={{header|Perl}}==
<
sub cusip_check_digit {
Line 2,889 ⟶ 3,469:
);
print "$_ $test_data{$_}" . cusip_check_digit($_) . "\n" for sort keys %test_data;</
{{out}}
<pre>037833100 Apple Incorporated
Line 2,899 ⟶ 3,479:
=={{header|Phix}}==
<!--<
<span style="color: #004080;">sequence</span> <span style="color: #000000;">cch</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
Line 2,940 ⟶ 3,520:
<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>
<!--</
{{out}}
<pre>
Line 2,952 ⟶ 3,532:
=={{header|PHP}}==
<
if (strlen($s) != 9) return false;
$sum = 0;
Line 2,990 ⟶ 3,570:
"68389X105");
foreach ($cusips as $cusip) echo $cusip . " -> " . (IsCusip($cusip) ? "valid" : "invalid") . "\n";</
{{out}}
<pre>
Line 3,001 ⟶ 3,581:
=={{header|PicoLisp}}==
<
(let (Str (mapcar char (chop Str)) S 0)
(for (I . C) (head 8 Str)
Line 3,029 ⟶ 3,609:
"38259P508"
"68389X106"
"68389X105" ) ) )</
{{out}}
<pre>(T T T NIL T)</pre>
=={{header|PowerShell}}==
<
function Get-CheckDigitCUSIP {
[CmdletBinding()]
Line 3,083 ⟶ 3,663:
"@ -split "`n"
$data |%{ Test-IsCUSIP $_.Split("`t")[0] }
</
True
True
Line 3,096 ⟶ 3,676:
Requires Python 3.6 for the string template literal in the print statement.
<
import math
Line 3,138 ⟶ 3,718:
for code in codes:
print(f'{code} -> {cusip_check(code)}')
</syntaxhighlight>
Output:
<pre>037833100 -> True
Line 3,151 ⟶ 3,731:
{{Works with|Python|3.7}}
Composing a set of pure functions, including a number of general and reusable abstractions:
<
from itertools import (cycle, islice, starmap)
Line 3,310 ⟶ 3,890:
# MAIN ---
if __name__ == '__main__':
main()</
{{Out}}
<pre>Test for validity as a CUSIP string:
Line 3,323 ⟶ 3,903:
=={{header|Quackery}}==
<
swap 0 swap
witheach
Line 3,348 ⟶ 3,928:
$ "037833100 17275R102 38259P508 594918104 68389X106 68389X105"
nest$ witheach task</
{{out}}
Line 3,362 ⟶ 3,942:
=={{header|Racket}}==
<
(require srfi/14)
Line 3,398 ⟶ 3,978:
(check-true (CUSIP? "594918104"))
(check-false (CUSIP? "68389X106"))
(check-true (CUSIP? "68389X105")))</
no output indicates all tests passed.
Line 3,406 ⟶ 3,986:
{{works with|Rakudo|2017.01}}
<syntaxhighlight lang=raku
my %chr = (flat 0..9, 'A'..'Z', <* @ #>) Z=> 0..*;
Line 3,423 ⟶ 4,003:
68389X106
68389X105
></
{{out}}
<pre>037833100: True
Line 3,434 ⟶ 4,014:
=={{header|REXX}}==
===idiomatic===
<
@.=
parse arg @.1 .
Line 3,465 ⟶ 4,045:
$=$ + #%10 + #//10
end /*k*/
return (10- $//10) // 10</
'''output''' when using the default input:
<pre>
Line 3,477 ⟶ 4,057:
===conciser function===
<
@.=
parse arg @.1 .
Line 3,502 ⟶ 4,082:
$=$ + #%10 + #//10
end /*k*/
return (10-$//10) // 10</
'''output''' is the same as the idiomatic REXX version. <br><br>
=={{header|Ring}}==
<
# Project : CUSIP
Line 3,535 ⟶ 4,115:
ok
if x >= ascii("A") and x <= ascii("Z")
v = x -
flag = 1
ok
Line 3,564 ⟶ 4,144:
see inputstr + " is invalid" + nl
ok
</syntaxhighlight>
Output:
<pre>
Line 3,573 ⟶ 4,153:
68389X106 is invalid
68389X105 is valid
</pre>
=={{header|RPL}}==
{{works with|Halcyon Calc|4.2.7}}
{| class="wikitable"
! RPL code
! Comment
|-
|
≪
SWAP ROT DUP2 ≤ OVER 5 ROLL ≤ AND
SWAP NUM ROT NUM - 1 + 0 '''IFTE'''
≫ ''''BTWEEN'''' STO
≪
0
1 8 '''FOR''' j
OVER j DUP SUB → c
≪ '''IF''' c "0" "9" '''BTWEEN'''
'''THEN''' LAST 1 -
'''ELSE IF''' c "A" "Z" '''BTWEEN'''
'''THEN''' LAST
9 +
'''ELSE IF''' "*@#" c POS
'''THEN''' LAST 35 +
'''END END END'''
j 2 MOD SWAP DUP DUP + '''IFTE'''
10 / LAST MOD SWAP IP + +
≫ '''NEXT'''
10 SWAP 10 MOD - 10 MOD
SWAP 9 DUP SUB STR→ ==
≫ ''''CUSIP?'''' STO
|
'''BTWEEN''' ''( "char" "from" "to" -- pos )''
evaluate "from" ≤ "char ≤ "to"
if yes, return relative position from "from"
'''CUSIP?''' ''( "CUSIP" -- boolean )''
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...)
v := p + 9
else if c = "*", "@", "#" then
v := 36, 37, 38
if i is even then v := v × 2
sum := sum + int ( v div 10 ) + v mod 10
repeat
get (10 - (sum mod 10)) mod 10
return true if equal to 9th digit
|}
{{in}}
<pre>
≪ { "037833100" "17275R102" "38259P508" "594918104" "68389X106" "68389X105" } → tests
≪ {} 1 tests SIZE FOR n
tests n GET n CUSIP? "Yes" "No" IFTE + NEXT
≫ ≫ EVAL
</pre>
{{out}}
<pre>
1: { "Yes" "Yes" "Yes" "Yes" "No" "Yes" }
</pre>
=={{header|Ruby}}==
===Following pseudocode===
<
#!/usr/bin/env ruby
Line 3,617 ⟶ 4,264:
end
</syntaxhighlight>
Output:
Line 3,630 ⟶ 4,277:
===More concise===
Since it uses methods like chain, to_h, sum, and infinite Range syntax (0..), this needs a Ruby version > 2.5
<
TABLE = ("0".."9").chain("A".."Z", %w(* @ #)).zip(0..).to_h
Line 3,642 ⟶ 4,289:
CUSIPs = %w(037833100 17275R102 38259P508 594918104 68389X106 68389X105)
CUSIPs.each{|cusip| puts "#{cusip}: #{valid_CUSIP? cusip}"}
</syntaxhighlight>
=={{header|Rust}}==
<
if cusip.len() != 9 {
return false;
Line 3,687 ⟶ 4,334:
println!("{} -> {}", code, cusip_check(code))
}
}</
Output:
Line 3,700 ⟶ 4,347:
=={{header|Scala}}==
{{Out}}See it running in your browser by [https://scalafiddle.io/sf/jwxwWpq/0 ScalaFiddle (JavaScript, non JVM)] or by [https://scastie.scala-lang.org/OBrz9l14Rm2C6tV8tiwhWg Scastie (JVM)].
<
val candidates = Seq("037833100", "17275R102", "38259P508", "594918104", "68389X106", "68389X105")
Line 3,715 ⟶ 4,362:
var v = 0
if (c >= '0' && c <= '9') v = c - 48
else if (c >= 'A' && c <= 'Z') v = c -
else if (c == '*') v = 36
else if (c == '@') v = 37
Line 3,727 ⟶ 4,374:
}
}</
=={{header|SNOBOL4}}==
<
* cusip.sno
* -- Committee on Uniform Security Identification Procedures
Line 3,779 ⟶ 4,426:
68389X10
68389X1059
68389x105</
{{out}}
<pre>037833100 valid.
Line 3,793 ⟶ 4,440:
=={{header|Swift}}==
<
var value: String
Line 3,859 ⟶ 4,506:
print("Valid")
}
}</
{{out}}
Line 3,872 ⟶ 4,519:
=={{header|Tcl}}==
=== Direct translation of pseudocode ===
<
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]
}
Line 3,909 ⟶ 4,556:
set cusip [string range $cusip 0 end-1]
expr {$last eq [Cusip-Check-Digit $cusip]}
}</
=== More idiomatic Tcl ===
<
if {[string length $code] != 9} {
return false
Line 3,928 ⟶ 4,575:
}
expr {$sum % 10 == 0}
}</
=== Common test harness ===
<
foreach {cusip name} {
037833100 "Apple Incorporated"
Line 3,944 ⟶ 4,591:
}
}
test</
=== Output ===
Line 3,955 ⟶ 4,602:
Oracle Corporation valid</pre>
=={{header|
{{trans|Go}}
<syntaxhighlight lang="v (vlang)">fn is_cusip(s string) bool {
mut sum
for i in 0..8
c
match true
c >= '0'[0] &&
}
c >= 'A'[0] && c
}
c == '*'[0]
v = 36
}
c == '@'[0] {
v = 37
}
c == '#'[0] {
v = 38
}
else
}
}
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")
}
}</syntaxhighlight>
{{out}}
<pre>
037833100 -> correct
17275R102 -> correct
38259P508 -> correct
594918104 -> correct
68389X106 -> incorrect
68389X105 -> correct
</pre>
=={{header|Wren}}==
{{trans|Go}}
<
if (s.count != 9) return false
var sum = 0
Line 4,059 ⟶ 4,678:
v = c - 48
} else if (c >= 65 && c <= 90) { // 'A' to 'Z'
v = c -
} else if (s[i] == "*") {
v = 36
Line 4,086 ⟶ 4,705:
var b = (isCusip.call(candidate)) ? "correct" : "incorrect"
System.print("%(candidate) -> %(b)")
}</
{{out}}
Line 4,099 ⟶ 4,718:
=={{header|XPL0}}==
<
func Valid(Cusip); \Return 'true' if valid CUSIP code
Line 4,137 ⟶ 4,756:
CrLf(0);
];
]</
{{out}}
Line 4,149 ⟶ 4,768:
</pre>
=={{header|
<syntaxhighlight lang=zig>const std = @import("std");
const print = std.debug.print;
pub fn CusipCheckDigit(cusip: *const [9:0]u8) bool {
var sum: i32 = 0;
while (i < 8) {
else if (c <=
}
else if
v
}
else if (c == '@')
v = 37;
else if (c == '#')
}
if (i % 2 == 1) {
}
}
return (cusip[8] - 48 == @mod((10 - @mod(sum, 10)), 10));
}
pub fn main() void {
const cusips = [_]*const [9:0]u8 {
"037833100",
"38259P508",
"594918104",
"68389X106",
"68389X105"
print("{s} -> {}\n", .{cusip, CusipCheckDigit(cusip)});
}
}
</syntaxhighlight>
=={{header|zkl}}==
<
var [const] vs=[0..9].chain(["A".."Z"],T("*","@","#")).pump(String);
try{
Line 4,208 ⟶ 4,828:
((10 - sum%10)%10 == cusip[8].toInt()) and cusip.len()==9
}catch{ False }
}</
<
"38259P508", "594918104", "68389X106", "68389X105")){
println(cusip,": ",cusipCheckDigit(cusip));
}</
{{out}}
<pre>
|