43 lines
1.7 KiB
Text
43 lines
1.7 KiB
Text
scope # Damm Algorithm
|
|
|
|
# returns true if the check digit of s is correct according to the Damm algorithm,
|
|
# false otherwise #
|
|
local proc hasValidDammCheckDigit( s :: string ) :: boolean
|
|
|
|
local constant operationTable
|
|
:= seq( (/ 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 to size s do
|
|
local constant nextDigit := abs s[ sPos ] - abs "0";
|
|
if 0 <= nextDigit and nextDigit <= 9 then
|
|
interimDigit := operationTable[ interimDigit + 1, nextDigit + 1 ]
|
|
else
|
|
error( "Invalid Damm digit: [" & s[ sPos ] & "]" )
|
|
fi
|
|
od;
|
|
return interimDigit = 0
|
|
end;
|
|
|
|
local proc testDammAlgorithm( s :: string, expectedResult :: boolean )
|
|
local constant isValid := hasValidDammCheckDigit( s );
|
|
printf( "check digit of %s is %s%s\n", s
|
|
, if isValid then "valid" else "invalid" fi
|
|
, if isValid == expectedResult then "" else " *** NOT AS EXPECTED" fi
|
|
)
|
|
end;
|
|
|
|
# test cases
|
|
testDammAlgorithm( "5724", true );
|
|
testDammAlgorithm( "5727", false );
|
|
testDammAlgorithm( "112946", true )
|
|
end
|