Created
August 7, 2012 18:22
-
-
Save mwgamera/3288051 to your computer and use it in GitHub Desktop.
Verhoeff36 in Lua
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/lua | |
do | |
local N = 18 | |
-- Group operation in D18 | |
local d18_op = {} | |
for i = 1, N do | |
d18_op[i] = {} | |
for j = 1, N do | |
d18_op[i][j] = 1 + (i + j - 2) % N | |
end | |
end | |
for i = 1, N do | |
for j = N+1, 2*N do | |
d18_op[i][j] = 1+N + (i + j - 2) % N | |
end | |
end | |
for i = N+1, 2*N do | |
d18_op[i] = {} | |
for j = 1, N do | |
d18_op[i][j] = 1+N + (i - j) % N | |
end | |
end | |
for i = N+1, 2*N do | |
for j = N+1, 2*N do | |
d18_op[i][j] = 1 + (i - j) % N | |
end | |
end | |
-- Inverse element | |
local d18_inv = {} | |
d18_inv[1] = 1 | |
for i = 2, N do | |
d18_inv[i] = N-i+2 | |
end | |
for i = N+1, 2*N do | |
d18_inv[i] = i | |
end | |
-- The permutation | |
local perm = {} | |
do | |
local b, i, p = {}, 1, { | |
30,1,33,12,36,21,8,28,3,5,20,29,31,2,6,13,4,10,17, | |
23,7,34,9,25,27,22,15,11,35,32,16,26,18,14,24,19 | |
} | |
while i <= #p do | |
local c, l = {}, 0 | |
while not b[i] do | |
l = l + 1 | |
c[l] = p[i] | |
b[i] = true | |
i = p[i] | |
end | |
for j = 1, #c do | |
perm[c[j]] = {} | |
for k = 1, #c do | |
perm[c[j]][k] = c[1 + (j + k - 2) % #c] | |
end | |
end | |
i = 1; while i <= #p and b[i] do i = i + 1 end | |
end | |
end | |
-- ASCII translation tables | |
local a2i = {} | |
for i = 0x00, 0xff do a2i[i] = nil end | |
for i = 0x30, 0x39 do a2i[i] = i - 0x30 + 1 end | |
for i = 0x41, 0x5a do a2i[i] = i - 0x41 + 11 end | |
for i = 0x61, 0x7a do a2i[i] = i - 0x61 + 11 end | |
local i2a = {} | |
for i = 0, 10 do i2a[i] = i + 0x30 end | |
for i =10,2*N do i2a[i] = i + 0x41 - 10 end | |
-- Calculate check digit | |
local function ver(str, i) | |
local c, l = 1, #str | |
while l > 0 do | |
local ch = a2i[str:byte(l)] | |
if ch then | |
c = d18_op[c][perm[ch][1+(i-1)%#(perm[ch])]] | |
i = i + 1 | |
end | |
l = l - 1 | |
end | |
return c | |
end | |
-- Verify correctness of check digit | |
local function verify(str) | |
return ver(str, 1) == 1 | |
end | |
-- Append check digit to given string | |
local function append(str) | |
local c = d18_inv[ver(str, 2)] | |
c = c + 0x30 - 1 | |
if c > 0x39 then c = c + 7 end | |
return str .. string.format("%c", c) | |
end | |
-- Act as command line utility | |
if arg then | |
local ap, lt = false, false | |
for i = 1,#arg do | |
if not lt and (arg[i]=="-a" or arg[i]=="-c" or arg[i]=="--") then | |
if arg[i] == "-a" then ap = true end | |
if arg[i] == "-c" then ap = false end | |
if arg[i] == "--" then lt = true end | |
else | |
if ap then | |
print(append(arg[i])) | |
else | |
if verify(arg[i]) then | |
print(arg[i], "OK") | |
else | |
print(arg[i], "FAIL") | |
end | |
end | |
end | |
end | |
end | |
-- Export public interface as module | |
return { | |
verify = verify, | |
append = append | |
} | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment