43 lines
1.9 KiB
Text
43 lines
1.9 KiB
Text
|
|
do -- Damm Algorithm
|
||
|
|
|
||
|
|
-- returns true if the check digit of s is correct according to the Damm algorithm,
|
||
|
|
-- false otherwise #
|
||
|
|
local function hasValidDammCheckDigit( s : string ) : boolean
|
||
|
|
|
||
|
|
local operationTable <const> = { { 0, 3, 1, 7, 5, 9, 8, 6, 4, 2 } -- as per wikipedia example
|
||
|
|
, { 7, 0, 9, 2, 1, 5, 4, 8, 6, 3 }
|
||
|
|
, { 4, 2, 0, 6, 8, 7, 1, 3, 5, 9 }
|
||
|
|
, { 1, 7, 5, 0, 9, 8, 3, 4, 2, 6 }
|
||
|
|
, { 6, 1, 2, 3, 0, 4, 5, 9, 7, 8 }
|
||
|
|
, { 3, 6, 7, 4, 2, 0, 9, 5, 8, 1 }
|
||
|
|
, { 5, 8, 6, 9, 7, 2, 0, 1, 3, 4 }
|
||
|
|
, { 8, 9, 4, 5, 3, 6, 2, 0, 1, 7 }
|
||
|
|
, { 9, 4, 3, 8, 6, 1, 7, 2, 0, 5 }
|
||
|
|
, { 2, 5, 8, 1, 4, 3, 6, 7, 9, 0 }
|
||
|
|
}
|
||
|
|
local interimDigit = 0
|
||
|
|
for sPos = 1, # s do
|
||
|
|
local nextDigit <const> = string.byte( s[ sPos ] ) - string.byte( "0" )
|
||
|
|
if 0 <= nextDigit <= 9 then
|
||
|
|
interimDigit = operationTable[ interimDigit + 1 ][ nextDigit + 1 ]
|
||
|
|
else
|
||
|
|
error( $"Invalid Damm digit: [{s[ sPos ]}]" )
|
||
|
|
end
|
||
|
|
end
|
||
|
|
return interimDigit == 0
|
||
|
|
end
|
||
|
|
|
||
|
|
local function testDammAlgorithm( s : string, expectedResult : boolean ) : void
|
||
|
|
local isValid <const> = hasValidDammCheckDigit( s )
|
||
|
|
print( $"check digit of {s} is "
|
||
|
|
.. if isValid then "valid" else "invalid" end
|
||
|
|
.. if isValid == expectedResult then "" else " *** NOT AS EXPECTED" end
|
||
|
|
)
|
||
|
|
end
|
||
|
|
|
||
|
|
-- test cases
|
||
|
|
testDammAlgorithm( "5724", true )
|
||
|
|
testDammAlgorithm( "5727", false )
|
||
|
|
testDammAlgorithm( "112946", true )
|
||
|
|
end
|