Skip to content

Instantly share code, notes, and snippets.

@mwgamera
Created August 7, 2012 18:22
Show Gist options
  • Save mwgamera/3288051 to your computer and use it in GitHub Desktop.
Save mwgamera/3288051 to your computer and use it in GitHub Desktop.
Verhoeff36 in Lua
#!/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