Validate International Securities Identification Number: Difference between revisions

Content added Content deleted
(→‎{{header|Kotlin}}: Updated example see https://github.com/dkandalov/rosettacode-kotlin for details)
(Added COBOL)
Line 330: Line 330:


USER></pre>
USER></pre>

=={{header|COBOL}}==
By Steve Williams {{works with|GnuCOBOL}}
<lang cobol> >>SOURCE FORMAT FREE
*> this is gnucobol 2.0
identification division.
program-id. callISINtest.
data division.
working-storage section.
01 ISINtest-result binary-int.
procedure division.
start-callISINtest.
display 'should be valid ' with no advancing
call 'ISINtest' using 'US0378331005' ISINtest-result
perform display-ISINtest-result
display 'should not be valid ' with no advancing
call 'ISINtest' using 'US0373831005' ISINtest-result
perform display-ISINtest-result
display 'should not be valid ' with no advancing
call 'ISINtest' using 'U50378331005' ISINtest-result
perform display-ISINtest-result
display 'should not be valid ' with no advancing
call 'ISINtest' using 'US03378331005' ISINtest-result
perform display-ISINtest-result
display 'should be valid ' with no advancing
call 'ISINtest' using 'AU0000XVGZA3' ISINtest-result
perform display-ISINtest-result
display 'should be valid ' with no advancing
call 'ISINtest' using 'AU0000VXGZA3' ISINtest-result
perform display-ISINtest-result
display 'should be valid ' with no advancing
call 'ISINtest' using 'FR0000988040' ISINtest-result
perform display-ISINtest-result
stop run
.
display-ISINtest-result.
evaluate ISINtest-result
when 0
display ' is valid'
when -1
display ' invalid length '
when -2
display ' invalid countrycode '
when -3
display ' invalid base36 digit '
when -4
display ' luhn test failed'
when other
display ' invalid return code ' ISINtest-result
end-evaluate
.
end program callISINtest.

identification division.
program-id. ISINtest.
data division.
working-storage section.
01 country-code-values value
'ADAEAFAGAIALAMAOAQARASATAUAWAXAZBABBBDBEBFBGBHBIBJBLBMBNBOBQBRBS'
& 'BTBVBWBYBZCACCCDCFCGCHCICKCLCMCNCOCRCUCVCWCXCYCZDEDJDKDMDODZECEE'
& 'EGEHERESETFIFJFKFMFOFRGAGBGDGEGFGGGHGIGLGMGNGPGQGRGSGTGUGWGYHKHM'
& 'HNHRHTHUIDIEILIMINIOIQIRISITJEJMJOJPKEKGKHKIKMKNKPKRKWKYKZLALBLC'
& 'LILKLRLSLTLULVLYMAMCMDMEMFMGMHMKMLMMMNMOMPMQMRMSMTMUMVMWMXMYMZNA'
& 'NCNENFNGNINLNONPNRNUNZOMPAPEPFPGPHPKPLPMPNPRPSPTPWPYQARERORSRURW'
& 'SASBSCSDSESGSHSISJSKSLSMSNSOSRSSSTSVSXSYSZTCTDTFTGTHTJTKTLTMTNTO'
& 'TRTTTVTWTZUAUGUMUSUYUZVAVCVEVGVIVNVUWFWSYEYTZAZMZW'.
03 country-codes occurs 249
ascending key country-code
indexed by cc-idx.
05 country-code pic xx.

01 b pic 99.
01 base36-digits pic x(36) value
'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'.

01 i pic 99.
01 p pic 99.
01 luhn-number pic x(20).
01 luhntest-result binary-int.

linkage section.
01 test-number any length.
01 ISINtest-result binary-int.

procedure division using test-number ISINtest-result.
start-ISINtest.
display space test-number with no advancing

*> format test
if function length(test-number) <> 12
move -1 to ISINtest-result
goback
end-if

*> countrycode test
search all country-codes
at end
move -2 to ISINtest-result
goback
when test-number(1:2) = country-code(cc-idx)
continue
end-search

*> convert each character from base 36 to base 10
*> and add to the luhn-number
move 0 to p
perform varying i from 1 by 1 until i > 12
if test-number(i:1) >= '0' and <= '9'
move test-number(i:1) to luhn-number(p + 1:1)
add 1 to p
else
perform varying b from 9 by 1 until b > 35
or base36-digits(b + 1:1) = test-number(i:1)
continue
end-perform
if b > 35
move -3 to ISINtest-result
goback
end-if
move b to luhn-number(p + 1:2)
add 2 to p
end-if
end-perform

call 'luhntest' using luhn-number(1:p) luhntest-result
if luhntest-result <> 0
move -4 to ISINtest-result
goback
end-if

move 0 to ISINtest-result
goback
.
end program ISINtest.

identification division.
program-id. luhntest.
data division.
working-storage section.
01 i pic S99.
01 check-sum pic 999.
linkage section.
01 test-number any length.
01 luhntest-result binary-int.
procedure division using test-number luhntest-result.
start-luhntest.
display space test-number with no advancing
move 0 to check-sum

*> right to left sum the odd numbered digits
compute i = function length(test-number)
perform varying i from i by -2 until i < 1
add function numval(test-number(i:1)) to check-sum
end-perform
display space check-sum with no advancing

*> right to left double sum the even numbered digits
compute i = function length(test-number) - 1
perform varying i from i by -2 until i < 1
add function numval(test-number(i:1)) to check-sum
add function numval(test-number(i:1)) to check-sum
*> convert a two-digit double sum number to a single digit
if test-number(i:1) >= '5'
subtract 9 from check-sum
end-if
end-perform
display space check-sum with no advancing

if function mod(check-sum,10) = 0
move 0 to luhntest-result *> success
else
move -1 to luhntest-result *> failure
end-if
goback
.
end program luhntest.</lang>

{{out}}
<pre>prompt$ cobc -xj ISINTest.cbl
should be valid US0378331005 30280378331005 027 050 is valid
should not be valid US0373831005 30280373831005 022 046 luhn test failed
should not be valid U50378331005 invalid countrycode
should not be valid US03378331005 invalid length
should be valid AU0000XVGZA3 1030000033311635103 018 030 is valid
should be valid AU0000VXGZA3 1030000031331635103 018 030 is valid
should be valid FR0000988040 15270000988040 020 050 is valid</pre>


=={{header|Common Lisp}}==
=={{header|Common Lisp}}==