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