(phixonline)-->
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