Description
The Verhoeff algorithm is a checksum formula for error detection developed by the Dutch mathematician Jacobus Verhoeff and first published in 1969. It was the first decimal check digit algorithm which detects all single-digit errors, and all transposition errors involving two adjacent digits, which was at the time thought impossible with such a code.

As the workings of the algorithm are clearly described in the linked Wikipedia article they will not be repeated here.

Task

Write routines, methods, procedures etc. in your language to generate a Verhoeff checksum digit for non-negative integers of any length and to validate the result. A combined routine is also acceptable.

The more mathematically minded may prefer to generate the 3 tables required from the description provided rather than to hard-code them.

Write your routines in such a way that they can optionally display digit by digit calculations as in the Wikipedia example.

Use your routines to calculate check digits for the integers: 236, 12345 and 123456789012 and then validate them. Also attempt to validate the same integers if the check digits in all cases were 9 rather than what they actually are.

Display digit by digit calculations for the first two integers but not for the third.

Related task

   Damm algorithm


const multiplicationtable = [
    0  1  2  3  4  5  6  7  8  9;
    1  2  3  4  0  6  7  8  9  5;
    2  3  4  0  1  7  8  9  5  6;
    3  4  0  1  2  8  9  5  6  7;
    4  0  1  2  3  9  5  6  7  8;
    5  9  8  7  6  0  4  3  2  1;
    6  5  9  8  7  1  0  4  3  2;
    7  6  5  9  8  2  1  0  4  3;
    8  7  6  5  9  3  2  1  0  4;
    9  8  7  6  5  4  3  2  1  0]
 
const permutationtable = [
    0  1  2  3  4  5  6  7  8  9;
    1  5  7  6  2  8  3  0  9  4;
    5  8  0  3  7  9  6  1  4  2;
    8  9  1  6  0  4  3  5  2  7;
    9  4  5  3  1  2  6  8  7  0;
    4  2  8  6  5  7  3  9  0  1;
    2  7  9  3  8  0  6  4  1  5;
    7  0  4  6  9  1  3  2  5  8]
 
const inv = [0, 4, 3, 2, 1, 5, 6, 7, 8, 9]
 
"""
    verhoeffchecksum(n::Integer, validate=true, terse=true, verbose=false)
 
Calculate the Verhoeff checksum over `n`.
Terse mode or with single argument: return true if valid (last digit is a correct check digit).
If checksum mode, return the expected correct checksum digit.
If validation mode, return true if last digit checks correctly.
"""
function verhoeffchecksum(n::Integer, validate=true, terse=true, verbose=false)
    verbose && println("\n", validate ? "Validation" : "Check digit",
        " calculations for '$n':\n\n", " i  nᵢ  p[i,nᵢ]  c\n------------------")
    # transform number list
    c, dig = 0, reverse(digits(validate ? n : 10 * n))
    for i in length(dig):-1:1
        ni = dig[i]
        p = permutationtable[(length(dig) - i) % 8 + 1, ni + 1]
        c = multiplicationtable[c + 1, p + 1]
        verbose && println(lpad(length(dig) - i, 2), "  $ni      $p    $c")
    end
    verbose && !validate && println("\ninv($c) = $(inv[c + 1])")
    !terse && println(validate ? "\nThe validation for '$n' is $(c == 0 ?
        "correct" : "incorrect")." : "\nThe check digit for '$n' is $(inv[c + 1]).")
    return validate ? c == 0 : inv[c + 1]
end
 
for args in [(236, false, false, true), (2363, true, false, true), (2369, true, false, true),
    (12345, false, false, true), (123451, true, false, true), (123459, true, false, true),
    (123456789012, false, false), (1234567890120, true, false), (1234567890129, true, false)]
        verhoeffchecksum(args...)
end
 