CUSIP: Difference between revisions

6,832 bytes added ,  2 months ago
(Dialects of BASIC moved to the BASIC section.)
(12 intermediate revisions by 8 users not shown)
Line 55:
<syntaxhighlight lang=11l>F cusip_check(=cusip)
I cusip.len != 9
X.throw ValueError(‘CUSIP must be 9 characters’)
 
cusip = cusip.uppercase()
Line 1,279:
v = c - '0';
} else if ('A' <= c && c <= 'Z') {
v = c - '@A' + 10;
} else if (c = '*') {
v = 36;
} else if (c = '@') {
v = 37;
} else if (c = '#') {
v = 38;
Line 1,606 ⟶ 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,658 ⟶ 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,875 ⟶ 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}}==
Line 2,820 ⟶ 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 {
{{works with|langur|0.8.5}}
<syntaxhighlight lang=langur>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 {
Line 2,833 ⟶ 2,999:
if not .v: return false
.v = .v[1]-1
if .i div 2: .v x*= 2
_for += .v \ 10 + .v rem 10
}
Line 2,840 ⟶ 3,006:
}
 
val .candidates = wfw/037833100 17275R102 38259P508 594918104 68389X106 68389X105/
 
for .c in .candidates {
Line 2,847 ⟶ 3,013:
 
Following the pseudo-code would look more like the following.
 
{{works with|langur|0.8.5}}
{{trans|Go}}
<syntaxhighlight lang=langur>val .isCusip = ffn(.s) {
if not isString(.s) is not string or len(.s) != 9 {
return false
}
Line 2,859 ⟶ 3,023:
var .v = 0
 
givenswitch[and] .c {
# for given, default op between conditions is "and"
# for switch, default op between conditions is "or"
case >= '0', <= '9':
.v = .c-'0'
Line 2,875 ⟶ 3,037:
}
 
if .i div 2: .v x*= 2
_for += .v \ 10 + .v rem 10
}
Line 2,976 ⟶ 3,138:
{{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}}==
Line 3,946 ⟶ 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>
 
Line 4,395 ⟶ 4,669:
=={{header|Wren}}==
{{trans|Go}}
<syntaxhighlight lang=ecmascript"wren">var isCusip = Fn.new { |s|
if (s.count != 9) return false
var sum = 0
1,006

edits