61 lines
2.2 KiB
Text
61 lines
2.2 KiB
Text
with javascript_semantics
|
|
sequence d = {tagset(9,0)},
|
|
inv = tagset(9,0),
|
|
p = {tagset(9,0)}
|
|
for i=1 to 4 do d = append(d,extract(d[$],{2,3,4,5,1,7,8,9,10,6})) end for
|
|
for i=5 to 8 do d = append(d,reverse(d[-4])) end for
|
|
d = append(d,reverse(d[1]))
|
|
inv[2..5] = reverse(inv[2..5])
|
|
for i=1 to 7 do p = append(p,extract(p[$],{2,6,8,7,3,9,4,1,10,5})) end for
|
|
|
|
-- alternatively, if you prefer:
|
|
--constant d = {{0,1,2,3,4,5,6,7,8,9},
|
|
-- {1,2,3,4,0,6,7,8,9,5},
|
|
-- {2,3,4,0,1,7,8,9,5,6},
|
|
-- {3,4,0,1,2,8,9,5,6,7},
|
|
-- {4,0,1,2,3,9,5,6,7,8},
|
|
-- {5,9,8,7,6,0,4,3,2,1},
|
|
-- {6,5,9,8,7,1,0,4,3,2},
|
|
-- {7,6,5,9,8,2,1,0,4,3},
|
|
-- {8,7,6,5,9,3,2,1,0,4},
|
|
-- {9,8,7,6,5,4,3,2,1,0}},
|
|
-- inv = {0,4,3,2,1,5,6,7,8,9},
|
|
-- p = {{0,1,2,3,4,5,6,7,8,9},
|
|
-- {1,5,7,6,2,8,3,0,9,4},
|
|
-- {5,8,0,3,7,9,6,1,4,2},
|
|
-- {8,9,1,6,0,4,3,5,2,7},
|
|
-- {9,4,5,3,1,2,6,8,7,0},
|
|
-- {4,2,8,6,5,7,3,9,0,1},
|
|
-- {2,7,9,3,8,0,6,4,1,5},
|
|
-- {7,0,4,6,9,1,3,2,5,8}}
|
|
|
|
function verhoeff(string n, bool validate=false, show_workings=false)
|
|
string {s,t} = iff(validate?{n,"Validation"}:{n&'0',"Check digit"})
|
|
if show_workings then
|
|
printf(1,"%s calculations for `%s`:\n", {t, n})
|
|
printf(1," i ni p(i,ni) c\n")
|
|
printf(1,"------------------\n")
|
|
end if
|
|
integer c = 0
|
|
for i=1 to length(s) do
|
|
integer ni = s[-i]-'0',
|
|
pi = p[remainder(i-1,8)+1][ni+1]
|
|
c = d[c+1][pi+1]
|
|
if show_workings then
|
|
printf(1,"%2d %d %d %d\n", {i-1, ni, pi, c})
|
|
end if
|
|
end for
|
|
integer ch = inv[c+1]+'0'
|
|
string r = iff(validate?iff(c=0?"":"in")&"correct"
|
|
:"`"&ch&"`")
|
|
printf(1,"The %s for `%s` is %s\n\n",{lower(t),n,r})
|
|
return ch
|
|
end function
|
|
|
|
constant tests = {"236", "12345", "123456789012"}
|
|
for i=1 to length(tests) do
|
|
bool show_workings = (i<=2)
|
|
integer ch = verhoeff(tests[i],false,show_workings)
|
|
assert(verhoeff(tests[i]&ch,true,show_workings)=='0')
|
|
assert(verhoeff(tests[i]&'9',true,show_workings)!='0')
|
|
end for
|