Damm algorithm

Revision as of 17:37, 26 March 2022 by rosettacode>Dejan94 (R language)

The Damm algorithm is a checksum algorithm which detects all single digit errors and adjacent transposition errors.

Task
Damm algorithm
You are encouraged to solve this task according to the task description, using any language you may know.


The algorithm is named after H. Michael Damm.


Task

Verify the checksum, stored as last digit of an input.



11l

Translation of: Python

<lang 11l>V matrix = [

   [0, 3, 1, 7, 5, 9, 8, 6, 4, 2],
   [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]

]

F damm(Int num) -> Bool

  V row = 0
  L(digit) String(num)
     row = :matrix[row][Int(digit)]
  R row == 0

L(test) [5724, 5727, 112946]

  print(test"\t Validates as: "damm(test))</lang>
Output:
5724     Validates as: 1B
5727     Validates as: 0B
112946   Validates as: 1B


==8080 Assembly

==

<lang 8080asm> org 100h jmp demo ;;; Given an 0-terminated ASCII string containing digits in [DE], ;;; see if it matches its check digit. Returns with zero flag set ;;; if the string matches. damm: mvi c,0 ; Interim digit in C, starts off at 0. ldax d ; Get current byte from string inx d ; Advance the pointer ana a ; Is the byte zero? jnz $+5 ; If not, go look up interim digit cmp c ; But if so, see if the interim digit is also zero ret ; And return whether this was the case sui '0' ; Subtract ASCII 0 mov b,a ; Keep digit to be processed in B mov a,c ; Calculate C*10 (interim digit row index) add a ; * 2 add a ; * 4 add c ; * 5 add a ; * 10 add b ; Add column index lxi h,dammit add l ; Table lookup (assuming H doesn't change, i.e. it mov l,a ; doesn't cross a page boundary). mov c,m ; Get new interim digit from table jmp damm+2 ; And check next character ;;; Table of interim digits ;;; NOTE: must not cross page boundary dammit: db 0,3,1,7,5,9,8,6,4,2 db 7,0,9,2,1,5,4,8,6,3 db 4,2,0,6,8,7,1,3,5,9 db 1,7,5,0,9,8,3,4,2,6 db 6,1,2,3,0,4,5,9,7,8 db 3,6,7,4,2,0,9,5,8,1 db 5,8,6,9,7,2,0,1,3,4 db 8,9,4,5,3,6,2,0,1,7 db 9,4,3,8,6,1,7,2,0,5 db 2,5,8,1,4,3,6,7,9,0 ;;; Demo code: see if the argument on the CP/M command line ;;; matches its input. demo: lxi h,80h ; Zero-terminate input mov e,m mvi d,0 inx d dad d mov m,d lxi d,82h ; Command line argument, skipping first space call damm ; See if it validates mvi c,9 lxi d,ok ; Print OK... jz 5 ; ...if the checksum matches, lxi d,no ; Print NOT OK otherwise. jmp 5 no: db 'NOT ' ok: db 'OK$'</lang>

Output:
A>damm 5724
OK
A>damm 5727
NOT OK
A>damm 112946
OK
A>damm 112949
NOT OK

8086 Assembly

<lang asm> cpu 8086 bits 16 section .text org 100h jmp demo ;;; Given a 0-terminated ASCII string containing digits in ;;; [DS:SI], see if the check digit matches. Returns with zero flag ;;; set if it matches. damm: xor cl,cl ; Interim digit starts out at 0 mov bx,.tab ; Index for table lookup .dgt: lodsb ; Get next string byte test al,al ; If it is zero, we're done jz .out sub al,'0' ; Make ASCII digit mov ah,cl ; Table lookup, AH = interim digit aad ; AL += AH * 10 (such handy instructions the 8086 has) cs xlatb ; AL = CS:table[AL] mov cl,al ; CL = new interim digit jmp .dgt ; Get next string .out: test cl,cl ; Interim digit should be zero at the end ret .tab: db 0,3,1,7,5,9,8,6,4,2 ; Table can be stored as part of the db 7,0,9,2,1,5,4,8,6,3 ; code db 4,2,0,6,8,7,1,3,5,9 db 1,7,5,0,9,8,3,4,2,6 db 6,1,2,3,0,4,5,9,7,8 db 3,6,7,4,2,0,9,5,8,1 db 5,8,6,9,7,2,0,1,3,4 db 8,9,4,5,3,6,2,0,1,7 db 9,4,3,8,6,1,7,2,0,5 db 2,5,8,1,4,3,6,7,9,0 ;;; Demo: see if the argument on the MS-DOS command line is valid demo: xor bh,bh ; Zero-terminate the input mov bl,[80h] mov [bx+81h],bh mov si,82h ; Start of input skipping first space call damm ; Is it valid? mov dx,ok ; If so, print OK jz .print mov dx,no ; Otherwise, print NOT OK .print: mov ah,9 int 21h ret section .data no: db 'NOT ' ok: db 'OK$'</lang>

Output:
C:\>damm86 5724
OK
C:\>damm86 5725
NOT OK
C:\>damm86 112946
OK
C:\>damm86 112949
NOT OK


Action!

<lang Action!>BYTE FUNC Damm(CHAR ARRAY a)

 BYTE ARRAY table=[
   0 3 1 7 5 9 8 6 4 2
   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]
 BYTE i,x,c
 x=0
 FOR i=1 TO a(0)
 DO
   c=a(i)
   IF c<'0 OR c>'9 THEN
     RETURN (0)
   FI
   c==-'0
   x=table(x*10+c)
 OD
 IF x=0 THEN
   RETURN (1)
 FI

RETURN (0)

PROC Test(CHAR ARRAY a)

 BYTE i
 Print(a) Print(" -> ")
 IF Damm(a)=1 THEN
   PrintE("valid")
 ELSE
   PrintE("invalid")
 FI

RETURN

PROC Main()

 Test("5724")
 Test("5727")
 Test("112946")
 Test("112949")

RETURN</lang>

Output:

Screenshot from Atari 8-bit computer

5724 -> valid
5727 -> invalid
112946 -> valid
112949 -> invalid

Ada

<lang Ada>with Ada.Text_IO;

procedure Damm_Algorithm is

  function Damm (Input : in String) return Boolean
  is
     subtype Digit is Character range '0' .. '9';
     Table : constant array (Digit, Digit) of Digit :=
       (('0', '3', '1', '7', '5', '9', '8', '6', '4', '2'),
        ('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'));
     Intern : Digit := '0';
  begin
     for D of Input loop
        Intern := Table (Intern, D);
     end loop;
     return Intern = '0';
  end Damm;
  procedure Put_Damm (Input : in String) is
     use Ada.Text_IO;
  begin
     Put_Line ("Damm of " & Input & " validates as " & Damm (Input)'Image);
  end Put_Damm;

begin

  Put_Damm ("5724");
  Put_Damm ("5727");
  Put_Damm ("112946");
  Put_Damm ("112949");

end Damm_Algorithm;</lang>

Output:
Damm of 5724 validates as TRUE
Damm of 5727 validates as FALSE
Damm of 112946 validates as TRUE
Damm of 112949 validates as FALSE

ALGOL 68

<lang algol68>BEGIN

   # returns TRUE if the check digit of s is correct according to the Damm algorithm, #
   # FALSE otherwise #
   PROC has valid damm check digit = ( STRING s )BOOL:
        BEGIN
           # operation table - as per wikipedia example #
           [,]INT operation table =
               ( [,]INT( ( 0, 3, 1, 7, 5, 9, 8, 6, 4, 2 )
                       , ( 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 )
                       )
               ) [ AT 0, AT 0 ]
               ;
           INT interim digit := 0;
           FOR s pos FROM LWB s TO UPB s DO
               INT next digit = ABS s[ s pos ] - ABS "0";
               IF next digit < 0 OR next digit > 9 THEN
                   # invalid digit #
                   print( ( "Invalid damm digit: ", s[ s pos ], newline ) );
                   stop
               ELSE
                   # have a valid digit #
                   interim digit := operation table[ interim digit, next digit ]
               FI
           OD;
           interim digit = 0
        END # has valid damm check digit # ;

   # test the damm algorithm #
   PROC test damm algorithm = ( STRING s, BOOL expected )VOID:
        BEGIN
           BOOL valid = has valid damm check digit( s );
           print( ( "check digit of ", s, " is "
                  , IF valid THEN "valid" ELSE "invalid" FI
                  , IF valid = expected THEN "" ELSE " *** NOT AS EXPECTED" FI
                  , newline
                  )
                )
        END # test damm algorithm # ;
   # test cases - as per other language samples #
   test damm algorithm( "5724",   TRUE  );
   test damm algorithm( "5727",   FALSE );
   test damm algorithm( "112946", TRUE  )

END</lang>

Output:
check digit of 5724 is valid
check digit of 5727 is invalid
check digit of 112946 is valid

APL

Works with: Dyalog APL

This is a function that takes a vector of digits and returns a boolean.

<lang apl> damm←{⎕IO←0

   tbl←⍉⍪0 3 1 7 5 9 8 6 4 2
   tbl⍪← 7 0 9 2 1 5 4 8 6 3
   tbl⍪← 4 2 0 6 8 7 1 3 5 9
   tbl⍪← 1 7 5 0 9 8 3 7 2 6
   tbl⍪← 6 1 2 3 0 4 5 9 7 8
   tbl⍪← 3 6 7 4 2 0 9 5 8 1
   tbl⍪← 5 8 6 9 7 2 0 1 3 4
   tbl⍪← 8 9 4 5 3 6 2 0 1 7
   tbl⍪← 9 4 3 8 6 1 7 2 0 5
   tbl⍪← 2 5 8 1 4 3 6 7 9 0
   0={tbl[⍵;⍺]}/⌽0,⍵
}</lang>
Output:
      damm 5 7 2 4
1
      damm 5 7 2 5
0
      damm 1 1 2 9 4 6
1
      damm 1 1 2 9 4 9
0

AppleScript

<lang applescript>-- Return a check digit value for the given integer value or numeric string. -- The result is 0 if the input's last digit is already a valid check digit for it. on damm(n)

   set digits to {n mod 10}
   set n to n div 10
   repeat until (n is 0)
       set beginning of digits to n mod 10
       set n to n div 10
   end repeat
   
   script o
       property table : {0, 3, 1, 7, 5, 9, 8, 6, 4, 2, ¬
           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}
   end script
   set interim to 0
   repeat with d in digits
       set interim to item (interim * 10 + d + 1) of o's table -- AppleScript indices are 1-based.
   end repeat
   
   return interim

end damm

-- Task code: local testNumbers, possibilities, output, n set testNumbers to {5724, 57240, 572400, 87591, 100} -- Include a number with a check digit actually generated by the handler. tell (random number 1000000) to set end of testNumbers to it * 10 + (my damm(it)) set possibilities to {" is invalid", " is valid"} set output to {} repeat with n in testNumbers

   set end of output to (n as text) & item (((damm(n) is 0) as integer) + 1) of possibilities

end repeat return output</lang>

Output:

<lang applescript>{"5724 is valid", "57240 is valid", "572400 is valid", "87591 is invalid", "100 is invalid", "3922446 is valid"}</lang>

ARM Assembly

<lang>.text .global _start @@@ Check if the zero-terminated ASCII string in [r0], @@@ which should contain a decimal number, has a @@@ matching check digit. Zero flag set if true, @@@ check digit returned in r0. damm: mov r1,#0 @ R1 = interim digit ldr r2,=3f @ R2 = table base address 1: ldrb r3,[r0],#1 @ Load byte tst r3,r3 @ Zero yet? beq 2f @ If so, stop sub r3,r3,#'0 @ Subtract ASCII 0 lsl r1,r1,#1 @ Table lookup add r1,r1,r1,lsl#2 @ R3 = R1*10 + R3 add r3,r1,r3 ldrb r1,[r2,r3] @ R1 = new interim digit b 1b @ Next value 2: movs r0,r1 @ Set flag according to r0. bx lr 3: .byte 0,3,1,7,5,9,8,6,4,2 @ Since the table is constant, .byte 7,0,9,2,1,5,4,8,6,3 @ it can be stored as part of .byte 4,2,0,6,8,7,1,3,5,9 @ the subroutine. .byte 1,7,5,0,9,8,3,4,2,6 @ This way the OS will even mark .byte 6,1,2,3,0,4,5,9,7,8 @ it as read-only, so we can .byte 3,6,7,4,2,0,9,5,8,1 @ be sure nothing changes it. .byte 5,8,6,9,7,2,0,1,3,4 .byte 8,9,4,5,3,6,2,0,1,7 .byte 9,4,3,8,6,1,7,2,0,5 .byte 2,5,8,1,4,3,6,7,9,0 .align 4 @ Instructions must be word-aligned @@@ Grab the argument from the command line, and see @@@ if it matches. _start: pop {r0} @ Is there even an argument? cmp r0,#2 movne r7,#1 @ If not, exit immediately swine #0 add sp,sp,#4 @ Discard program name pop {r0} @ Grab argument bl damm @ Check if it matches ldreq r1,=pass @ If yes, say 'pass' ldrne r1,=fail @ If not, say 'fail' mov r0,#1 @ Print string to stdout mov r2,#5 @ Both are 5 characters mov r7,#4 @ Write syscall = 4 swi #0 mov r0,#0 @ Exit mov r7,#1 swi #0 pass: .ascii "Pass\n" fail: .ascii "Fail\n"</lang>

Output:
$ for x in 5724 5725 112946 112949; do echo -n $x:; ./damm $x; done
5724:Pass
5725:Fail
112946:Pass
112949:Fail

Arturo

<lang rebol>table: [

   [0 3 1 7 5 9 8 6 4 2]
   [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]

]

digits: function [x][map split x => [to :integer]] damm?: function [z][zero? fold digits z .seed: 0 => [get get table]]

test: function [str][

   result: switch damm? str -> "valid"
                            -> "invalid"
   print [str "is" result]

]

loop ["5724" "5727" "112946" "112949"] => test</lang>

Output:
5724 is valid 
5727 is invalid 
112946 is valid 
112949 is invalid

AutoHotkey

<lang AutoHotkey>Damm(num){ row := 1, Damm := [[0,3,1,7,5,9,8,6,4,2] ,[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]] for i, v in StrSplit(SubStr(num, 1, -1)){ ++row := Damm[row, v+1] } return (SubStr(num, 0)=row-1 && !Damm[row, row]) }</lang> Examples:<lang AutoHotkey>result := "" for i, num in [5724, 5727, 112946, 112949] result .= num "`tis " (Damm(num) ? "valid" : "not valid") "`n" MsgBox % result</lang>

Outputs:

5724	is valid
5727	is not valid
112946	is valid
112949	is not valid

AWK

<lang AWK># syntax: GAWK -f DAMM_ALGORITHM.AWK BEGIN {

   damm_init()
   leng = split("5724,5727,112946",arr,",") # test cases
   for (i=1; i<=leng; i++) {
     n = arr[i]
     printf("%s %s\n",damm_check(n),n)
   }
   exit(0)

} function damm_check(n, a,i) {

   a = 0
   for (i=1; i<=length(n); i++) {
     a = substr(damm[a],substr(n,i,1)+1,1)
   }
   return(a == 0 ? "T" : "F")

} function damm_init() {

  1. 0123456789
   damm[0] = "0317598642"
   damm[1] = "7092154863"
   damm[2] = "4206871359"
   damm[3] = "1750983426"
   damm[4] = "6123045978"
   damm[5] = "3674209581"
   damm[6] = "5869720134"
   damm[7] = "8945362017"
   damm[8] = "9438617205"
   damm[9] = "2581436790"

}</lang>

Output:
T 5724
F 5727
T 112946

BASIC

<lang basic>10 DEFINT D,I,X,Y: DIM DT(9,9) 20 FOR Y=0 TO 9: FOR X=0 TO 9: READ DT(X,Y): NEXT X,Y 30 INPUT N$: IF N$="" THEN END 40 D=0 50 FOR I=1 TO LEN(N$): D=DT(VAL(MID$(N$,I,1)),D): NEXT I 60 IF D THEN PRINT "FAIL" ELSE PRINT "PASS" 70 GOTO 30 100 DATA 0,3,1,7,5,9,8,6,4,2 110 DATA 7,0,9,2,1,5,4,8,6,3 120 DATA 4,2,0,6,8,7,1,3,5,9 130 DATA 1,7,5,0,9,8,3,4,2,6 140 DATA 6,1,2,3,0,4,5,9,7,8 150 DATA 3,6,7,4,2,0,9,5,8,1 160 DATA 5,8,6,9,7,2,0,1,3,4 170 DATA 8,9,4,5,3,6,2,0,1,7 180 DATA 9,4,3,8,6,1,7,2,0,5 190 DATA 2,5,8,1,4,3,6,7,9,0</lang>

Output:
? 5724
PASS
? 5727
FAIL
? 112946
PASS
? 112949
FAIL

BCPL

<lang bcpl>get "libhdr"

let damm(ns) = valof $( let dt = table

       0,3,1,7,5,9,8,6,4,2,
       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
   let idgt = 0
   for i=1 to ns%0
       test '0' <= ns%i <= '9'
           do idgt := dt!(ns%i-'0' + 10*idgt)
           or resultis false
   resultis idgt = 0

$)

let check(ns) be

   writef("%S: %S*N", ns, damm(ns) -> "pass", "fail")

let start() be $( check("5724")

   check("5727")
   check("112946")
   check("112949")

$)</lang>

Output:
5724: pass
5727: fail
112946: pass
112949: fail

BQN

Translation of: J

<lang bqn>table ← >⟨ 0‿3‿1‿7‿5‿9‿8‿6‿4‿2

          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 ⟩


Digits ← 10{⌽𝕗|⌊∘÷⟜𝕗⍟(↕1+·⌊𝕗⋆⁼1⌈⊢)}

Damm ← {0=0(table⊑˜⋈)˜´⌽Digits 𝕩}

Damm¨5724‿5727‿112946</lang> <lang>⟨ 1 0 1 ⟩</lang>

Try It!

C

<lang c>#include <stdbool.h>

  1. include <stddef.h>
  2. include <stdio.h>

bool damm(unsigned char *input, size_t length) {

   static const unsigned char table[10][10] = {
       {0, 3, 1, 7, 5, 9, 8, 6, 4, 2},
       {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},
   };
   
   unsigned char interim = 0;
   for (size_t i = 0; i < length; i++) {
       interim = table[interim][input[i]];
   }
   return interim == 0;

}

int main() {

   unsigned char input[4] = {5, 7, 2, 4};
   puts(damm(input, 4) ? "Checksum correct" : "Checksum incorrect");
   return 0;

}</lang>

Output:
Checksum correct

C#

Translation of: Java

<lang csharp>using System;

namespace DammAlgorithm {

   class Program {
       static int[,] table = {
           {0, 3, 1, 7, 5, 9, 8, 6, 4, 2},
           {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},
       };
       static bool Damm(string s) {
           int interim = 0;
           foreach (char c in s) {
               interim = table[interim, c - '0'];
           }
           return interim == 0;
       }
       static void Main(string[] args) {
           int[] numbers = { 5724, 5727, 112946, 112949 };
           foreach (int number in numbers) {
               bool isValid = Damm(number.ToString());
               if (isValid) {
                   Console.WriteLine("{0,6} is valid", number);
               }
               else {
                   Console.WriteLine("{0,6} is invalid", number);
               }
           }
       }
   }

}</lang>

Output:
  5724 is valid
  5727 is invalid
112946 is valid
112949 is invalid

C++

Translation of: C# – C sharp

<lang cpp>#include <sstream>

const int TABLE[][10] = { {0, 3, 1, 7, 5, 9, 8, 6, 4, 2}, {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}, };

using std::string; bool damm(string s) { int interim = 0; for (char c : s) { interim = TABLE[interim][c - '0']; } return interim == 0; }

int main() { auto numbers = { 5724, 5727, 112946, 112949 }; for (int num : numbers) { using std::stringstream; stringstream ss; ss << num; bool isValid = damm(ss.str()); if (isValid) { printf("%6d is valid\n", num); } else { printf("%6d is invalid\n", num); } }

return 0; }</lang>

Output:
  5724 is valid
  5727 is invalid
112946 is valid
112949 is invalid

Caché ObjectScript

<lang cos>Class Utils.Check [ Abstract ] {

ClassMethod Damm(num As %Integer, mode As %Integer = 1) As %Integer { TRY { I mode=0 RETURN ..Damm(num,2)=0 S res=0, str=num S table=[ [0, 3, 1, 7, 5, 9, 8, 6, 4, 2], [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] ] F i=1:1:$L(str) S res=table.%Get(res).%Get($E(str,i)) I mode=1 S res=num_res } CATCH { S res="" } Q res }

}</lang>

Examples:
USER>For  { Read n Quit:n=""  Write ": "_##class(Utils.Check).Damm(n, 0), ! }
5724: 1
5727: 0
112946: 1
112949: 0

USER>w ##class(Utils.Check).Damm(11294)
112946
USER>

Clojure

<lang clojure>(def tbl [[0 3 1 7 5 9 8 6 4 2]

         [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]])

(defn damm? [digits]

 (= 0 (reduce #(nth (nth tbl %1) %2) 0 
   (map #(Character/getNumericValue %) (seq digits)))))</lang>
Output:
=> (damm? "5724")
true
=> (damm? "5727")
false
=> (damm? "112946")
true

CLU

<lang clu>% Verify that the Damm check digit of a string of digits is correct. % Signals 'bad_format' if the string contains non-digits. damm = proc (s: string) returns (bool) signals (bad_format)

   ai = array[int]
   aai = array[ai]
   own damm_table: aai := aai$[0: 
       ai$[0: 0,3,1,7,5,9,8,6,4,2],
       ai$[0: 7,0,9,2,1,5,4,8,6,3],
       ai$[0: 4,2,0,6,8,7,1,3,5,9],
       ai$[0: 1,7,5,0,9,8,3,4,2,6],
       ai$[0: 6,1,2,3,0,4,5,9,7,8],
       ai$[0: 3,6,7,4,2,0,9,5,8,1],
       ai$[0: 5,8,6,9,7,2,0,1,3,4],
       ai$[0: 8,9,4,5,3,6,2,0,1,7],
       ai$[0: 9,4,3,8,6,1,7,2,0,5],
       ai$[0: 2,5,8,1,4,3,6,7,9,0]
   ]
   
   interim: int := 0
   for c: char in string$chars(s) do
       d: int := int$parse(string$c2s(c)) resignal bad_format
       interim := damm_table[interim][d]
   end
   
   return(interim = 0)

end damm

% Checks start_up = proc ()

   po: stream := stream$primary_output()
   tests: sequence[string] := sequence[string]$[
       "5724", "5727", "112946", "112949"
   ]
   
   for test: string in sequence[string]$elements(tests) do
       stream$puts(po, test || ": ")
       if damm(test) then
           stream$putl(po, "pass")
       else
           stream$putl(po, "fail")
       end
   end

end start_up</lang>

Output:
5724: pass
5727: fail
112946: pass
112949: fail

Cowgol

<lang cowgol>include "cowgol.coh";

  1. Damm test on number given as ASCII string
  2. Returns check digit

sub damm(num: [uint8]): (chk: uint8) is

   var table: uint8[] := {
       0,3,1,7,5,9,8,6,4,2,
       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
   };
   
   chk := 0;
   while [num] != 0 loop
       chk := table[(chk<<1) + (chk<<3) + ([num] - '0')];
       num := @next num;
   end loop;

end sub;

  1. Test and print

sub test(num: [uint8]) is

   print(num);
   print(":");
   if damm(num) == 0 then
       print("Pass\n");
   else
       print("Fail\n");
   end if;

end sub;

test("5724"); test("5727"); test("112946"); test("112949");</lang>

Output:
5724:Pass
5727:Fail
112946:Pass
112949:Fail

D

<lang D>import std.stdio;

auto table = [

   [0, 3, 1, 7, 5, 9, 8, 6, 4, 2],
   [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],

];

bool damm(string s) {

   int interim = 0;
   foreach (c; s) {
       interim = table[interim][c - '0'];
   }
   return interim == 0;

}

void main() {

   import std.conv : to;
   auto numbers = [5724, 5727, 112946, 112949];
   foreach (number; numbers) {
       bool isValid = damm(number.to!string());
       writef("%6d is ", number);
       if (isValid) {
           writeln("valid");
       } else {
           writeln("invalid");
       }
   }

}</lang>

Output:
  5724 is valid
  5727 is invalid
112946 is valid
112949 is invalid

Delphi

See Pascal.

Dyalect

<lang dyalect>let table = [

   [0, 3, 1, 7, 5, 9, 8, 6, 4, 2],
   [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]

]

func damm(s) {

   var interim = 0
   for c in s {
       interim = table[interim][c - '0']
   }
   return interim == 0;

}

let numbers = [5724, 5727, 112946, 112949] for number in numbers {

   let isValid = damm(number.ToString())
   if isValid {
       print("\(number) is valid")
   } else {
       print("\(number) is invalid")
   }

}</lang>

Output:
5724 is valid
5727 is invalid
112946 is valid
112949 is invalid

F#

<lang fsharp>open System

let TABLE = [|

   [|0; 3; 1; 7; 5; 9; 8; 6; 4; 2|];
   [|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|];

|]

let damm str =

   let rec helper (v:string) interim =
       if v.Length = 0 then 0 = interim
       else helper (v.Substring(1)) (TABLE.[interim].[(int (v.[0])) - (int '0')])
   helper str 0

[<EntryPoint>] let main _ =

   let numbers = [|5724; 5727; 112946; 112949|]
   for number in numbers do
       let isValid = damm (number.ToString())
       if isValid then
           printfn "%6d is valid" number
       else
           printfn "%6d is invalid" number
   0 // return an integer exit code

</lang>

Output:
  5724 is valid
  5727 is invalid
112946 is valid
112949 is invalid

Factor

<lang factor>USING: interpolate kernel math math.parser qw sequences ;

CONSTANT: table {

   { 0 3 1 7 5 9 8 6 4 2 }
   { 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 }

}

damm? ( str -- ? )
   0 [ digit> swap table nth nth ] reduce zero? ;

qw{ 5724 5727 112946 112949 } [ dup damm? "" "in" ? [I ${} is ${}validI] nl ] each</lang>

Output:
5724 is valid
5727 is invalid
112946 is valid
112949 is invalid


Forth

Works with: gforth version 0.7.3

<lang forth>: newdigit ( col row -- u ) 10 * + C" 0317598642709215486342068713591750983426612304597836742095815869720134894536201794386172052581436790" 1+ + c@ 48 - ;

nextdigit ( addr -- addr+1 u ) dup c@ 48 - swap 1+ swap ;
damm ( c u -- u )

0 rot rot 0 do

 nextdigit
 rot newdigit swap

loop drop

isdamm? damm 0= if ." yes" else ." no" then ;
.damm

2dup damm rot rot type 48 + emit

</lang>
Output:
s" 5724" isdamm? yes ok
s" 5727" isdamm? no ok
s" 572" .damm 5724 ok

Fortran

Thanks to the ability standardised in F90 to define an array with a lower bound other than one, this can be achieved without the need for annoying offsets, as in A(i + 1) instead of just A(i). However, right from the start, Fortran has stored arrays in column-major order, so statements that initialise two-dimensional arrays via a list of consecutive values can look odd when they are nicely laid out, because they will have to be be in transposed order. Alternatively, if the layout is the same as the expected (row,column) usage, the actual usage of the array will have to be (column,row). Rather than transpose a ten by ten matrix, this is the approach here. The continuation column has the (apparent) row count, but row zero can't have the digit zero in the continuation column as this is taken to be equivalent to a space (meaning "no continuation") just in case it is used for the first line of a statement to be continued. However, the letter o will do instead. A capital O looks too much like a 0...

Possibly a more useful function would be one that returned the check digit that must be appended to a sequence to provide the full sequence, as when preparing a checksummed sequence for output. For checking input, such a function would be applied to all but the last digit of the suspect sequence, and its result compared to the supplied last digit. But for simplicity here, all that is reported is "good" or "bad", without hints as to what would have been good. <lang Fortran> LOGICAL FUNCTION DAMM(DIGIT) !Check that a sequence of digits checks out.. Calculates according to the method of H. Michael Damm, described in 2004.

      CHARACTER*(*) DIGIT		!A sequence of digits only.
      INTEGER*1 OPTABLE(0:9,0:9)	!The special "Operation table" of the method.
      PARAMETER (OPTABLE = (/		!A set of constants...
    o  0, 3, 1, 7, 5, 9, 8, 6, 4, 2,	!        CAREFUL!
    1  7, 0, 9, 2, 1, 5, 4, 8, 6, 3,	!Fortran stores arrays in column-major order.
    2  4, 2, 0, 6, 8, 7, 1, 3, 5, 9,	!Despite the manifest row and column layout apparent here
    3  1, 7, 5, 0, 9, 8, 3, 4, 2, 6,	!This sequence of consecutive items will go into storage order.
    4  6, 1, 2, 3, 0, 4, 5, 9, 7, 8,	!The table resulting from this sequence of constants
    5  3, 6, 7, 4, 2, 0, 9, 5, 8, 1,	!Will appear to be transposed if referenced as (row,column)
    6  5, 8, 6, 9, 7, 2, 0, 1, 3, 4,	!What appears to be row=6 column=1 (counting from zero)
    7  8, 9, 4, 5, 3, 6, 2, 0, 1, 7,	!is to be accessed as OPTABLE(1,6) = 8, not OPTABLE(6,1)
    8  9, 4, 3, 8, 6, 1, 7, 2, 0, 5,	!Storage order is (0,0), (1,0), (2,0), ... (9,0)
    9  2, 5, 8, 1, 4, 3, 6, 7, 9, 0/))	!Followed by      (0,1), (1,1), (2,1), ... (9,1)
      INTEGER I,D,ID	!Assistants.
       ID = 0		!Here we go.
       DO I = 1,LEN(DIGIT)	!Step through the text.
         D = ICHAR(DIGIT(I:I)) - ICHAR("0")	!Convert to an integer. (ASCII or EBCDIC)
         IF (D.LT.0 .OR. D.GT.9) STOP "DAMM! Not a digit!"	!This shouldn't happen!
         ID = OPTABLE(D,ID)		!Transposed: D is the column index and ID the row.
       END DO			!On to the next.
       DAMM = ID .EQ. 0	!Somewhere, a check digit should ensure this.
     END FUNCTION DAMM	!Simple, fast, and alas, rarely used.

     LOGICAL DAMM	!Not a default type.

     WRITE (6,*) DAMM("5724"),"5724"
     WRITE (6,*) DAMM("5727"),"5727"
     WRITE (6,*) DAMM("112946"),"112946"

     END</lang>

Output:

 T 5724
 F 5727
 T 112946

FreeBASIC

<lang freebasic>' version 04-07-2018 ' compile with: fbc -s console

Function Damm(digit_str As String) As UInteger

   Dim As UInteger table(10,10) => { { 0, 3, 1, 7, 5, 9, 8, 6, 4, 2 } , _
  { 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 } }
   Dim As UInteger i, col_i, old_row_i, new_row_i
   For i = 0 To Len(digit_str) -1
       col_i = digit_str[i] - Asc("0")
       new_row_i = table(old_row_i, col_i)
       old_row_i = new_row_i
   Next
   Return new_row_i

End Function

' ------=< MAIN >=------

Data "5724", "5727", "112946", ""

Dim As UInteger checksum, t Dim As String test_string

Do

   Read test_string
   If test_string = "" Then Exit Do
   Print "Checksum test: ";test_string;
   checksum = Damm(test_string)
   If checksum = 0 Then
       Print " is valid"
   Else
       Print " is invalid"
   End If

Loop

' empty keyboard buffer While Inkey <> "" : Wend Print : Print "hit any key to end program" Sleep End</lang>

Output:
Checksum test: 5724 is valid
Checksum test: 5727 is invalid
Checksum test: 112946 is valid

Fōrmulæ

Fōrmulæ programs are not textual, visualization/edition of programs is done showing/manipulating structures but not text. Moreover, there can be multiple visual representations of the same program. Even though it is possible to have textual representation —i.e. XML, JSON— they are intended for storage and transfer purposes more than visualization and edition.

Programs in Fōrmulæ are created/edited online in its website, However they run on execution servers. By default remote servers are used, but they are limited in memory and processing power, since they are intended for demonstration and casual use. A local server can be downloaded and installed, it has no limitations (it runs in your own computer). Because of that, example programs can be fully visualized and edited, but some of them will not run if they require a moderate or heavy computation/memory resources, and no local server is being used.

In this page you can see the program(s) related to this task and their results.

Go

<lang go>package main

import "fmt"

var table = [10][10]byte{

   {0, 3, 1, 7, 5, 9, 8, 6, 4, 2},
   {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},

}

func damm(input string) bool {

   var interim byte
   for _, c := range []byte(input) {
       interim = table[interim][c-'0']
   }
   return interim == 0

}

func main() {

   for _, s := range []string{"5724", "5727", "112946", "112949"} {
       fmt.Printf("%6s  %t\n", s, damm(s))
   }

}</lang>

Output:
  5724  true
  5727  false
112946  true
112949  false

Groovy

Translation of: Java

<lang groovy>class DammAlgorithm {

   private static final int[][] TABLE = [
       [0, 3, 1, 7, 5, 9, 8, 6, 4, 2],
       [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],
   ]
   private static boolean damm(String s) {
       int interim = 0
       for (char c : s.toCharArray()) interim = TABLE[interim][c - ('0' as Character)]
       return interim == 0
   }
   static void main(String[] args) {
       int[] numbers = [5724, 5727, 112946, 112949]
       for (Integer number : numbers) {
           boolean isValid = damm(number.toString())
           if (isValid) {
               System.out.printf("%6d is valid\n", number)
           } else {
               System.out.printf("%6d is invalid\n", number)
           }
       }
   }

}</lang>

Output:
  5724 is valid
  5727 is invalid
112946 is valid
112949 is invalid

Haskell

<lang haskell>import Data.Char (digitToInt) import Text.Printf (printf)

damm :: String -> Bool damm = (==0) . foldl (\r -> (table !! r !!) . digitToInt) 0

 where
   table =
     [ [0, 3, 1, 7, 5, 9, 8, 6, 4, 2]
     , [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] ]

main :: IO () main = mapM_ (uncurry(printf "%6s is valid: %s\n") . ((,) <*> show . damm) . show)

 [5724, 5727, 112946, 112949]</lang>
Output:
  5724 is valid: True
  5727 is valid: False
112946 is valid: True
112949 is valid: False

J

Solution: <lang j>OpTbl=: _99 ". ];._2 noun define 0 3 1 7 5 9 8 6 4 2 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 )

getdigits=: 10&#.inv

getDamm=: verb define

 row=. 0
 for_digit. getdigits y do.
   row=. OpTbl {~ <row,digit    
 end.   

)

checkDamm=: 0 = getDamm</lang> Example Usage: <lang j> checkDamm&> 5724 5727 112946 1 0 1</lang>

Or,

<lang J>checkdamm=: {{0=((".;._2{{)n 0 7 4 1 6 3 5 8 9 2 3 0 2 7 1 6 8 9 4 5 1 9 0 5 2 7 6 4 3 8 7 2 6 0 3 4 9 5 8 1 5 1 8 9 0 2 7 3 6 4 9 5 7 8 4 0 2 6 1 3 8 4 1 3 5 9 0 2 7 6 6 8 3 4 9 5 1 0 2 7 4 6 5 2 7 8 3 1 0 9 2 3 9 6 8 1 4 7 5 0 }}){~<@,)/|.0,10#.inv y}}"0</lang>

<lang J> checkdamm 5724 5727 112946 1 0 1</lang>

We could probably replace that embedded table with something more concise if the description of the math behind the algorithm on the wikipedia page was more complete. (See talk page.)

Java

Translation of: Kotlin

<lang Java>public class DammAlgorithm {

   private static final int[][] table = {
       {0, 3, 1, 7, 5, 9, 8, 6, 4, 2},
       {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},
   };
   private static boolean damm(String s) {
       int interim = 0;
       for (char c : s.toCharArray()) interim = table[interim][c - '0'];
       return interim == 0;
   }
   public static void main(String[] args) {
       int[] numbers = {5724, 5727, 112946, 112949};
       for (Integer number : numbers) {
           boolean isValid = damm(number.toString());
           if (isValid) {
               System.out.printf("%6d is valid\n", number);
           } else {
               System.out.printf("%6d is invalid\n", number);
           }
       }
   }

}</lang>

Output:
  5724 is valid
  5727 is invalid
112946 is valid
112949 is invalid

JavaScript

<lang JavaScript>const table = [

   [0, 3, 1, 7, 5, 9, 8, 6, 4, 2],
   [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],
];

const lookup = (p, c) => table[p][parseInt(c, 10)] const damm = input => [...input].reduce(lookup, 0) === 0;

// ----------------------------------------------------------[ Tests ]---- const test = () => ["5724", "5727", "112946", "112949"].forEach(e =>

   console.log(`${e} => ${damm(e) ? 'Pass' : 'Fail'}`)

); test(); </lang>

Output:
5724 => Pass
5727 => Fail
112946 => Pass
112949 => Fail

jq

<lang jq>def checkdigit:

      [[0, 3, 1, 7, 5, 9, 8, 6, 4, 2],
       [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]]
     as $m
   | tostring | explode
     # "0" is 48
   | 0 == reduce (.[] - 48) as $d (0; $m[.][$d] );
  1. The task:

5724, 5727, 112946, 112949 | checkdigit as $d | [., $d] </lang>

Output:

<lang sh> [5724,true] [5727,false] [112946,true] [112949,false] </lang>

Julia

<lang julia>function checkdigit(n)

   matrix = (
       (0, 3, 1, 7, 5, 9, 8, 6, 4, 2),
       (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))
   row = 0
   for d in string(n)
       row = matrix[row + 1][d - '0' + 1]
   end
   return row

end

foreach(i -> println("$i validates as: ", checkdigit(string(i)) == 0), [5724, 5727, 112946])

</lang>

Output:
5724 validates as: true
5727 validates as: false
112946 validates as: true

Kotlin

<lang scala>// version 1.1.2

val table = arrayOf(

   intArrayOf(0, 3, 1,	7, 5, 9, 8, 6, 4, 2),
   intArrayOf(7, 0, 9, 2, 1, 5, 4, 8, 6, 3),
   intArrayOf(4, 2, 0, 6, 8, 7, 1, 3, 5, 9),
   intArrayOf(1, 7, 5, 0, 9, 8, 3, 4, 2, 6),
   intArrayOf(6, 1, 2, 3, 0, 4, 5, 9, 7, 8),
   intArrayOf(3, 6, 7, 4, 2, 0, 9, 5, 8, 1),
   intArrayOf(5, 8, 6, 9, 7, 2, 0, 1, 3, 4),
   intArrayOf(8, 9, 4, 5, 3, 6, 2, 0, 1, 7),
   intArrayOf(9, 4, 3, 8, 6, 1, 7, 2, 0, 5),
   intArrayOf(2, 5, 8, 1, 4, 3, 6, 7, 9, 0)

)

fun damm(s: String): Boolean {

   var interim = 0
   for (c in s) interim = table[interim][c - '0']
   return interim == 0

}

fun main(args: Array<String>) {

   val numbers = intArrayOf(5724, 5727, 112946, 112949)
   for (number in numbers) {
       val isValid = damm(number.toString())
       println("${"%6d".format(number)} is ${if (isValid) "valid" else "invalid"}")
   }

}</lang>

Output:
  5724 is valid
  5727 is invalid
112946 is valid
112949 is invalid

Liberty BASIC

<lang liberty basic>Dim DT(9, 9)

For y = 0 To 9

   For x = 0 To 9
       Read val
       DT(x, y) = val
   Next x

Next y

Input check$ While (check$ <> "")

   D = 0
   For i = 1 To Len(check$)
       D = DT(Val(Mid$(check$, i, 1)), D)
   Next i
   If D Then
       Print "Invalid"
   Else
       Print "Valid"
   End If
   Input check$

Wend End

DATA 0,3,1,7,5,9,8,6,4,2 DATA 7,0,9,2,1,5,4,8,6,3 DATA 4,2,0,6,8,7,1,3,5,9 DATA 1,7,5,0,9,8,3,4,2,6 DATA 6,1,2,3,0,4,5,9,7,8 DATA 3,6,7,4,2,0,9,5,8,1 DATA 5,8,6,9,7,2,0,1,3,4 DATA 8,9,4,5,3,6,2,0,1,7 DATA 9,4,3,8,6,1,7,2,0,5 DATA 2,5,8,1,4,3,6,7,9,0</lang>

Output:
?5724
Valid
?5727
Invalid
?112946
Valid
?112949
Invalid

Lua

<lang lua>local tab = {

   {0,3,1,7,5,9,8,6,4,2}, {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}

} function check( n )

   local idx, a = 0, tonumber( n:sub( 1, 1 ) )
   for i = 1, #n do
       a = tonumber( n:sub( i, i ) )
       if a == nil then return false end
       idx = tab[idx + 1][a + 1]
   end
   return idx == 0

end local n, r while( true ) do

   io.write( "Enter the number to check: " )
   n = io.read(); if n == "0" then break end
   r = check( n ); io.write( n, " is " )
   if not r then io.write( "in" ) end
   io.write( "valid!\n" )

end</lang>

Output:
Enter the number to check: 5724
5724 is valid!
Enter the number to check: 5727
5727 is invalid!
Enter the number to check: 112946
112946 is valid!
Enter the number to check: 0

M2000 Interpreter

<lang M2000 Interpreter> Module Damm_Algorithm{ Function Prepare { function OperationTable { data (0, 3, 1, 7, 5, 9, 8, 6, 4, 2) data (7, 0, 9, 2, 1, 5, 4, 8, 6, 3) data (4, 2, 0, 6, 8, 7, 1, 3, 5, 9) data (1, 7, 5, 0, 9, 8, 3, 4, 2, 6) data (6, 1, 2, 3, 0, 4, 5, 9, 7, 8) data (3, 6, 7, 4, 2, 0, 9, 5, 8, 1) data (5, 8, 6, 9, 7, 2, 0, 1, 3, 4) data (8, 9, 4, 5, 3, 6, 2, 0, 1, 7) data (9, 4, 3, 8, 6, 1, 7, 2, 0, 5) data (2, 5, 8, 1, 4, 3, 6, 7, 9, 0) =array([]) } Digits= Lambda (d) ->{ d$=str$(d,"") for i=1 to len(d$) data val(mid$(d$,i,1)) next =Array([]) } =Lambda a()=OperationTable(), Digits (N) -> { dim b() b()=Digits(N) m=0 for i=0 to len(b())-1 m=a(m)(b(i)) next i =m } } Damm=Prepare() Data 5724, 5727, 112946, 112940 while not empty over ' double the top of stack over Print number, Damm(number), Damm(number)=0 End While } Damm_Algorithm </lang>

Output:
  5724     0   True
  5727     9  False
112946     0   True
112940     5  False

MAD

<lang MAD> NORMAL MODE IS INTEGER

         R VERIFY DAMM CHECKSUM OF NUMBER
           INTERNAL FUNCTION(CKNUM)
           VECTOR VALUES DAMMIT = 
         0        0,3,1,7,5,9,8,6,4,2
         1     ,  7,0,9,2,1,5,4,8,6,3
         2     ,  4,2,0,6,8,7,1,3,5,9
         3     ,  1,7,5,0,9,8,3,4,2,6
         4     ,  6,1,2,3,0,4,5,9,7,8
         5     ,  3,6,7,4,2,0,9,5,8,1
         6     ,  5,8,6,9,7,2,0,1,3,4
         7     ,  8,9,4,5,3,6,2,0,1,7
         8     ,  9,4,3,8,6,1,7,2,0,5
         9     ,  2,5,8,1,4,3,6,7,9,0           
           DIMENSION DAMDGT(10)
           ENTRY TO DAMM.
           TMP=CKNUM
           THROUGH GETDGT, FOR NDGT=0, 1, TMP.E.0
           DAMDGT(NDGT) = TMP-TMP/10*10

GETDGT TMP = TMP/10

           INTRM = 0
           THROUGH CKDGT, FOR NDGT=NDGT, -1, NDGT.L.0

CKDGT INTRM = DAMMIT(INTRM*10 + DAMDGT(NDGT))

           FUNCTION RETURN INTRM.E.0
           END OF FUNCTION
           
         R TEST SOME NUMBERS
           THROUGH TEST, FOR VALUES OF N = 5724,5727,112946,112949
           WHENEVER DAMM.(N)
               PRINT FORMAT VALID,N
           OTHERWISE
               PRINT FORMAT INVAL,N

TEST END OF CONDITIONAL

           VECTOR VALUES VALID = $I9,S1,5HVALID*$
           VECTOR VALUES INVAL = $I9,S1,7HINVALID*$
           END OF PROGRAM

</lang>

Output:
     5724 VALID
     5727 INVALID
   112946 VALID
   112949 INVALID


Mathematica / Wolfram Language

<lang Mathematica>matrix = {{0, 3, 1, 7, 5, 9, 8, 6, 4, 2}, {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}};

Damm[num_Integer] := Module[{row},

 row = 0;
 Do[
  row = matrixrow + 1, d + 1
  ,
  {d, IntegerDigits[num]}
  ];
 row == 0
 ]

Damm /@ {5724, 5727, 112946}</lang>

Output:
{True, False, True}

Modula-2

This example does not show the output mentioned in the task description on this page (or a page linked to from here). Please ensure that it meets all task requirements and remove this message.
Note that phrases in task descriptions such as "print and display" and "print and show" for example, indicate that (reasonable length) output be a part of a language's solution.


<lang modula2>MODULE DammAlgorithm; FROM FormatString IMPORT FormatString; FROM Terminal IMPORT WriteString,WriteLn,ReadChar;

TYPE TA = ARRAY[0..9],[0..9] OF INTEGER; CONST table = TA{

       {0, 3, 1, 7, 5, 9, 8, 6, 4, 2},
       {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}
   };

PROCEDURE Damm(s : ARRAY OF CHAR) : BOOLEAN; VAR interim,i : INTEGER; BEGIN

   interim := 0;
   i := 0;
   WHILE s[i] # 0C DO
       interim := table[interim,INT(s[i])-INT('0')];
       INC(i);
   END;
   RETURN interim=0;

END Damm;

PROCEDURE Print(number : INTEGER); VAR

   isValid : BOOLEAN;
   buf : ARRAY[0..16] OF CHAR;

BEGIN

   FormatString("%i", buf, number);
   isValid := Damm(buf);
   WriteString(buf);
   IF isValid THEN
       WriteString(" is valid");
   ELSE
       WriteString(" is invalid");
   END;
   WriteLn;

END Print;

BEGIN

   Print(5724);
   Print(5727);
   Print(112946);
   Print(112949);
   ReadChar;

END DammAlgorithm.</lang>

Nim

<lang Nim> from algorithm import reverse

const Table = [[0, 3, 1, 7, 5, 9, 8, 6, 4, 2],

              [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]]

type Digit = range[0..9]

func isValid(digits: openArray[Digit]): bool =

 ## Apply Damm algorithm to check validity of a digit sequence.
 var interim = 0
 for d in digits:
   interim = Table[interim][d]
 result = interim == 0

proc toDigits(n: int): seq[Digit] =

 ## Return the digits of a number.
 var n = n
 while true:
   result.add(n mod 10)
   n = n div 10
   if n == 0:
     break
 result.reverse()

proc checkData(digits: openArray[Digit]) =

 ## Check if a digit sequence if valid.
 if isValid(digits):
   echo "Sequence ", digits, " is valid."
 else:
   echo "Sequence ", digits, " is invalid."

checkData(5724.toDigits) checkData(5727.toDigits) checkData([Digit 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 6, 7, 8, 9, 0, 1]) checkData([Digit 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 6, 7, 8, 9, 0, 8]) </lang>

Output:
Sequence [5, 7, 2, 4] is valid.
Sequence [5, 7, 2, 7] is invalid.
Sequence [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 6, 7, 8, 9, 0, 1] is valid.
Sequence [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 6, 7, 8, 9, 0, 8] is invalid.

Objeck

Translation of: C#

<lang objeck>class DammAlgorithm {

 @table : static : Int[,];
 function : Main(args : String[]) ~ Nil {
   @table := [
     [0, 3, 1, 7, 5, 9, 8, 6, 4, 2]
     [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]];
   numbers := [ 5724, 5727, 112946, 112949 ];
   each (i : numbers) {
     number := numbers[i];
     isValid := Damm(number->ToString());
     if (isValid) {
       "{$number} is valid"->PrintLine();
     }
     else {
       "{$number} is invalid"->PrintLine();
     };
   };
 }
 function : Damm(s : String) ~ Bool {
   interim := 0;
   each (i : s) {
     interim := @table[interim, s->Get(i) - '0'];
   };
   return interim = 0;
 }

}</lang>

Output:
5724 is valid
5727 is invalid
112946 is valid
112949 is invalid

Pascal

Works with: Free Pascal
Translation of: Modula-2

nearly copy&paste

<lang pascal>program DammAlgorithm; uses

 sysutils;

TYPE TA = ARRAY[0..9,0..9] OF UInt8; CONST table : TA =

               ((0,3,1,7,5,9,8,6,4,2),
                (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));

function Damm(s : string) : BOOLEAN; VAR

 interim,i : UInt8;

BEGIN

 interim := 0;
 i := 1;
 WHILE i <= length(s) DO
 Begin
   interim := table[interim,ORD(s[i])-ORD('0')];
   INC(i);
 END;
 Damm := interim=0;

END;

PROCEDURE Print(number : Uint32); VAR

   isValid : BOOLEAN;
   buf :string;

BEGIN

   buf := IntToStr(number);
   isValid := Damm(buf);
   Write(buf);
   IF isValid THEN
     Write(' is valid')
   ELSE
     Write(' is invalid');
   WriteLn;

END;

BEGIN

   Print(5724);
   Print(5727);
   Print(112946);
   Print(112949);
   Readln;

END.</lang>

Output:
5724 is valid
5727 is invalid
112946 is valid
112949 is invalid

Perl

<lang perl>sub damm {

   my(@digits) = split , @_[0];
   my @tbl =([< 0 3 1 7 5 9 8 6 4 2 >],
             [< 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 >]
             );
   my $row = 0;
   for my $col (@digits) { $row = $tbl[$row][$col] }
   not $row

}

for (5724, 5727, 112946) {

   print "$_:\tChecksum digit @{[damm($_) ?  : 'in']}correct.\n"

}</lang>

Output:
5724:	Checksum digit correct.
5727:	Checksum digit incorrect.
112946:	Checksum digit correct.

Phix

As phix uses 1-based indexes, 1 must be added to the operation table, and validity is given by ending on one, rather than zero.

constant tbl = sq_add(1,{{0, 3, 1, 7, 5, 9, 8, 6, 4, 2},
                         {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}})
 
function damm(string s)
    integer interim = 1
    for i=1 to length(s) do
        integer nxt = s[i]-'0'+1
        if nxt<1 or nxt>10 then return 0 end if
        interim = tbl[interim][nxt]
    end for
    return interim == 1
end function
 
constant tests = {"5724", "5727", "112946", "112949"}
for i=1 to length(tests) do
    string ti = tests[i]
    printf(1,"%7s is %svalid\n",{ti,iff(damm(ti)?"":"in")})
end for
Output:
   5724 is valid
   5727 is invalid
 112946 is valid
 112949 is invalid

PHP

<lang PHP><?php function lookup($r,$c) {

   $table = array(
       array(0, 3, 1, 7, 5, 9, 8, 6, 4, 2),
       array(7, 0, 9, 2, 1, 5, 4, 8, 6, 3),
       array(4, 2, 0, 6, 8, 7, 1, 3, 5, 9),
       array(1, 7, 5, 0, 9, 8, 3, 4, 2, 6),
       array(6, 1, 2, 3, 0, 4, 5, 9, 7, 8),
       array(3, 6, 7, 4, 2, 0, 9, 5, 8, 1),
       array(5, 8, 6, 9, 7, 2, 0, 1, 3, 4),
       array(8, 9, 4, 5, 3, 6, 2, 0, 1, 7),
       array(9, 4, 3, 8, 6, 1, 7, 2, 0, 5),
       array(2, 5, 8, 1, 4, 3, 6, 7, 9, 0),
   );
   return $table[$r][$c];

}

function isDammValid($input) {

   return array_reduce(str_split($input), "lookup", 0) == 0;

}

foreach(array("5724", "5727", "112946", "112949") as $i) {

   echo "{$i} is ".(isDammValid($i) ? "valid" : "invalid")."
";

} ?></lang>

Output:
5724 is valid
5727 is invalid
112946 is valid
112949 is invalid

PicoLisp

<lang PicoLisp>(setq *D

  (quote                                                                                                                               
     (0 3 1 7 5 9 8 6 4 2)                                                                                                             
     (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) ) )                                                                                                         

(de damm? (N)

  (let R 1                                                                                                                             
     (for N (mapcar format (chop N))                                                                                                   
        (setq R (inc (get *D R (inc N)))) )                                                                                            
     (= 1 R) ) )                                                                                                                       

(println (damm? 5724)) (println (damm? 5727)) (println (damm? 112946)) (println (damm? 112940))</lang>

Output:
T
NIL
T
NIL

PL/M

<lang plm>100H:

/* DAMM CHECKSUM FOR DECIMAL NUMBER IN GIVEN STRING */ CHECK$DAMM: PROCEDURE (PTR) BYTE;

   DECLARE PTR ADDRESS, CH BASED PTR BYTE;
   DECLARE DAMM DATA
       ( 0,3,1,7,5,9,8,6,4,2,
         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 );
   DECLARE I BYTE;
   I = 0;
   DO WHILE CH <> '$';
       I = DAMM((I*10) + (CH-'0'));
       PTR = PTR + 1;
   END;
   RETURN I = 0;

END CHECK$DAMM;

/* CP/M BDOS CALLS */ BDOS: PROCEDURE (FN, ARG);

   DECLARE FN BYTE, ARG ADDRESS;
   GO TO 5;

END BDOS;

PRINT: PROCEDURE (STR);

   DECLARE STR ADDRESS;
   CALL BDOS(9, STR);

END PRINT;

/* TESTS */ DECLARE TEST (4) ADDRESS; TEST(0) = .'5724$'; TEST(1) = .'5727$'; TEST(2) = .'112946$'; TEST(3) = .'112949$';

DECLARE N BYTE; DO N = 0 TO LAST(TEST);

   CALL PRINT(TEST(N));
   CALL PRINT(.': $');
   IF CHECK$DAMM(TEST(N)) THEN
       CALL PRINT(.'PASS$');
   ELSE
       CALL PRINT(.'FAIL$');
   CALL PRINT(.(13,10,'$'));

END;

CALL BDOS(0,0); EOF</lang>

Output:
5724: PASS
5727: FAIL
112946: PASS
112949: FAIL

PureBasic

<lang PureBasic>DataSection

 DT_Start:
       Data.b	0,3,1,7,5,9,8,6,4,2	

Data.b 7,0,9,2,1,5,4,8,6,3 Data.b 4,2,0,6,8,7,1,3,5,9 Data.b 1,7,5,0,9,8,3,4,2,6 Data.b 6,1,2,3,0,4,5,9,7,8 Data.b 3,6,7,4,2,0,9,5,8,1 Data.b 5,8,6,9,7,2,0,1,3,4 Data.b 8,9,4,5,3,6,2,0,1,7 Data.b 9,4,3,8,6,1,7,2,0,5 Data.b 2,5,8,1,4,3,6,7,9,0 EndDataSection

Procedure.i Adr(Row,Col) : ProcedureReturn ?DT_Start+Row+10*Col : EndProcedure

Procedure.b CheckDamm(Value.s)

 *ipc.Character=@Value : it=0  
 While *ipc\c
   it=PeekB(Adr(*ipc\c-'0',it)) : *ipc+SizeOf(Character)
 Wend
 ProcedureReturn Bool(it)

EndProcedure

If OpenConsole()

 Repeat
   Print("Check Damm: ") : i$=Input()
   If CheckDamm(i$) : PrintN(Space(12)+"FALSE") : Else : PrintN(Space(12)+"TRUE") : EndIf
 Until i$=""

EndIf End</lang>

Output:
Check Damm: 5724
            TRUE
Check Damm: 5727
            FALSE
Check Damm: 112946
            TRUE
Check Damm: 112949
            FALSE
Check Damm: 

Python

<lang Python>def damm(num: int) -> bool:

   row = 0
   for digit in str(num):
       row = _matrix[row][int(digit)] 
   return row == 0

_matrix = (

   (0, 3, 1, 7, 5, 9, 8, 6, 4, 2),
   (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)

)

if __name__ == '__main__':

   for test in [5724, 5727, 112946]:
       print(f'{test}\t Validates as: {damm(test)}')</lang>
Output:
5724     Validates as: True
5727     Validates as: False
112946   Validates as: True

Quackery

<lang Quackery> [ 0 swap witheach

     [ char 0 - dip
         [ table
           [ 0 3 1 7 5 9 8 6 4 2 ]
           [ 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 ] ]
       peek ] ]                      is damm      ( $ --> n )
 [ damm 0 = ]                        is dammvalid ( $ --> b )
 [ dup echo$ say " is "
   dammvalid not if [ say "not " ]
   say "valid." cr ]                 is validate  ( & -->   )
 $ "5724 5725 112946 112949"
 nest$ witheach validate</lang>
Output:
5724 is valid.
5725 is not valid.
112946 is valid.
112949 is not valid.

R

<lang R>Damm_algo <- function(number){

 row_i = 0
 
 iterable = strsplit(toString(number), "")1
 
 validation_matrix = 
   matrix(
     c(
       0, 3, 1, 7, 5, 9, 8, 6, 4, 2,
       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),
     nrow = 10, ncol = 10, byrow = T
   )
 
 for(digit in as.integer(iterable)){
   row_i = validation_matrix[row_i + 1, digit + 1]    #in R indexes start from 1 and not from zero
 }
 
 test <- ifelse(row_i == 0, "VALID", "NOT VALID")
 message(paste("Number", number, "is", test))

}

for(number in c(5724, 5727, 112946, 112949)){ Damm_algo(number)

 }</lang>
Output:
Number 5724 is VALID
Number 5727 is NOT VALID
Number 112946 is VALID
Number 112949 is NOT VALID

Racket

<lang racket>#lang racket/base (require racket/match)

(define operation-table

 #(#(0 3 1 7 5 9 8 6 4 2)
   #(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)))

(define (integer->digit-list n)

 (let loop ((n n) (a null))
   (if (zero? n) a (let-values (([q r] (quotient/remainder n 10))) (loop q (cons r a))))))

(define/match (check-digit n)

 [((list ds ...))
  (foldl
   (λ (d interim)
     (vector-ref (vector-ref operation-table interim) d))
   0 ds)]
 [((? integer? i))
  (check-digit (integer->digit-list i))])

(define/match (valid-number? n)

 [((? integer? i))
  (valid-number? (integer->digit-list i))]
 [((list ds ...))
  (zero? (check-digit ds))])

(module+ test

 (require rackunit)
 (check-equal? (integer->digit-list 572) '(5 7 2))
 (check-equal? (check-digit 572) 4)
 (check-equal? (check-digit '(5 7 2)) 4)
 (check-true (valid-number? 5724))
 (check-false (valid-number? 5274))
 (check-true (valid-number? 112946)))</lang>

No output from checks means that all tests passed.


Raku

(formerly Perl 6)

Works with: Rakudo version 2017.05

<lang perl6>sub damm ( *@digits ) {

   my @tbl = [0, 3, 1, 7, 5, 9, 8, 6, 4, 2],
             [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];
   my $row = 0;
   for @digits -> $col { $row = @tbl[$row][$col] }
   not $row

}

  1. Testing

for 5724, 5727, 112946 {

   say "$_:\tChecksum digit { damm( $_.comb ) ??  !! 'in' }correct."

}</lang>

Output:
5724:	Checksum digit correct.
5727:	Checksum digit incorrect.
112946:	Checksum digit correct.

REXX

manufactured table

<lang rexx>/* REXX */ Call init Call test 5724 Call test 5727 Call test 112946 Call test 112940 Exit

test: Parse Arg number int_digit=0 Do p=1 To length(number)

 d=substr(number,p,1)
 int_digit=grid.int_digit.d
 If p<length(number) Then cd=int_digit
 End

If int_digit=0 Then

 Say number 'is ok'

Else

 Say number 'is not ok, check-digit should be' cd '(instead of' d')'

Return

init: i=-2 Call setup '* 0 1 2 3 4 5 6 7 8 9' Call setup '0 0 3 1 7 5 9 8 6 4 2' Call setup '1 7 0 9 2 1 5 4 8 6 3' Call setup '2 4 2 0 6 8 7 1 3 5 9' Call setup '3 1 7 5 0 9 8 3 4 2 6' Call setup '4 6 1 2 3 0 4 5 9 7 8' Call setup '5 3 6 7 4 2 0 9 5 8 1' Call setup '6 5 8 6 9 7 2 0 1 3 4' Call setup '7 8 9 4 5 3 6 2 0 1 7' Call setup '8 9 4 3 8 6 1 7 2 0 5' Call setup '9 2 5 8 1 4 3 6 7 9 0' Return setup:

 Parse Arg list
 i=i+1
 Do col=-1 To 9
   grid.i.col=word(list,col+2)
   End
 Return</lang>
Output:
5724 is ok
5727 is not ok, check-digit should be 4 (instead of 7)
112946 is ok
112940 is not ok, check-digit should be 6 (instead of 0)

static table

Using a static table is over four times faster than manufacturing it. <lang rexx>/*REXX pgm uses H. Michael Damm's algorithm to validate numbers with suffixed check sum.*/

  @.0= 0317598642;  @.1= 7092154863;  @.2= 4206871359;  @.3= 1750983426;  @.4= 6123045978
  @.5= 3674209581;  @.6= 5869720134;  @.7= 8945362017;  @.8= 9438617205;  @.9= 2581436790

call Damm 5724, 5727, 112946, 112940 /*invoke Damm's algorithm for some #'s.*/ exit 0 /*stick a fork in it, we're all done. */ /*──────────────────────────────────────────────────────────────────────────────────────*/ Damm: do j=1 for arg(); x= arg(j); $= 0; z= right(x, 1)

           do p=1  for length(x);     g=$;      $= substr(@.$,  1 + substr(x, p, 1),   1)
           end   /*p*/
     if $==0  then say '   valid checksum digit '  z  " for "  x
              else say ' invalid checksum digit '  z  " for "  x    '   (should be'  g")"
     end   /*j*/;                return</lang>
output   when using the (internal) default inputs:
  
   valid checksum digit  4  for  5724
 invalid checksum digit  7  for  5727    (should be 4)
   valid checksum digit  6  for  112946
 invalid checksum digit  0  for  112940    (should be 6)

Ring

<lang ring># Project : Damm algorithm

matrix = [[0, 3, 1, 7, 5, 9, 8, 6, 4, 2],

              [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]]

see "5724" + encode(5724 ) + nl see "5727" + encode(5727 ) + nl see "112946" + encode(112946) + nl

func encode(n)

      check = 0
      for d in string(n)
          check = matrix[check+1][d-'0'+1]
      next
      if check = 0
         return " is valid"
      else
         return " is invalid"
      ok</lang>

Output:

5724 is valid
5727 is invalid
112946 is valid

Ruby

<lang ruby>TABLE = [

   [0,3,1,7,5,9,8,6,4,2], [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]

]

def damm_valid?(n) = n.digits.reverse.inject(0){|idx, a| TABLE[idx][a] } == 0

[5724, 5727, 112946].each{|n| puts "#{n}: #{damm_valid?(n) ? "" : "in"}valid"} </lang>

Output:
5724: valid

5727: invalid 112946: valid

Rust

<lang rust>fn damm(number: &str) -> u8 {

   static TABLE: [[u8; 10]; 10] = [
       [0, 3, 1, 7, 5, 9, 8, 6, 4, 2],
       [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],
   ];
   number.chars().fold(0, |row, digit| {
       let digit = digit.to_digit(10).unwrap();
       TABLE[row as usize][digit as usize]
   })

}

fn damm_validate(number: &str) -> bool {

   damm(number) == 0

}

fn main() {

   let numbers = &["5724", "5727", "112946"];
   for number in numbers {
       let is_valid = damm_validate(number);
       if is_valid {
           println!("{:>6} is valid", number);
       } else {
           println!("{:>6} is invalid", number);
       }
   }

}</lang>

Output:
  5724 is valid
  5727 is invalid
112946 is valid

Scala

Functional, (tail) recursive, concise and clean

<lang Scala>import scala.annotation.tailrec

object DammAlgorithm extends App {

 private val numbers = Seq(5724, 5727, 112946, 112949)
 @tailrec
 private def damm(s: String, interim: Int): String = {
   def table =
     Vector(
       Vector(0, 3, 1, 7, 5, 9, 8, 6, 4, 2),
       Vector(7, 0, 9, 2, 1, 5, 4, 8, 6, 3),
       Vector(4, 2, 0, 6, 8, 7, 1, 3, 5, 9),
       Vector(1, 7, 5, 0, 9, 8, 3, 4, 2, 6),
       Vector(6, 1, 2, 3, 0, 4, 5, 9, 7, 8),
       Vector(3, 6, 7, 4, 2, 0, 9, 5, 8, 1),
       Vector(5, 8, 6, 9, 7, 2, 0, 1, 3, 4),
       Vector(8, 9, 4, 5, 3, 6, 2, 0, 1, 7),
       Vector(9, 4, 3, 8, 6, 1, 7, 2, 0, 5),
       Vector(2, 5, 8, 1, 4, 3, 6, 7, 9, 0)
     )
   if (s.isEmpty) if (interim == 0) "✔" else "✘"
   else damm(s.tail, table(interim)(s.head - '0'))
 }
 for (number <- numbers) println(f"$number%6d is ${damm(number.toString, 0)}.")

}</lang>

Output:

See it running in your browser by ScalaFiddle (JavaScript, non JVM) or by Scastie (remote JVM).

Sidef

<lang ruby>func damm(digits) {

   static tbl = [
         [0, 3, 1, 7, 5, 9, 8, 6, 4, 2],
         [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],
   ]
   !digits.flip.reduce({|row,col| tbl[row][col] }, 0)

}

for n in [5724, 5727, 112946] {

   say "#{n}:\tChecksum digit #{ damm(n.digits) ?  : 'in'}correct."

}</lang>

Output:
5724:	Checksum digit correct.
5727:	Checksum digit incorrect.
112946:	Checksum digit correct.

uBasic/4tH

Translation of: Visual Basic .NET
Works with: v3.64

<lang>Push 0, 3, 1, 7, 5, 9, 8, 6, 4, 2: i = FUNC(_Data(0)) Push 7, 0, 9, 2, 1, 5, 4, 8, 6, 3: i = FUNC(_Data(i)) Push 4, 2, 0, 6, 8, 7, 1, 3, 5, 9: i = FUNC(_Data(i)) Push 1, 7, 5, 0, 9, 8, 3, 4, 2, 6: i = FUNC(_Data(i)) Push 6, 1, 2, 3, 0, 4, 5, 9, 7, 8: i = FUNC(_Data(i)) Push 3, 6, 7, 4, 2, 0, 9, 5, 8, 1: i = FUNC(_Data(i)) Push 5, 8, 6, 9, 7, 2, 0, 1, 3, 4: i = FUNC(_Data(i)) Push 8, 9, 4, 5, 3, 6, 2, 0, 1, 7: i = FUNC(_Data(i)) Push 9, 4, 3, 8, 6, 1, 7, 2, 0, 5: i = FUNC(_Data(i)) Push 2, 5, 8, 1, 4, 3, 6, 7, 9, 0: i = FUNC(_Data(i))

                                      ' Read the table

Push 112949, 112946, 5727, 5724 ' Put numbers on the stack

For i = 1 To Used() ' Read up to the number of stack items

 Print Using "______"; Tos();" is ";  ' Print the header
 If FUNC(_Damm (Str(Pop()))) Then Print "in";
 Print "valid"                        ' invalid only if Damm() returns TRUE

Next ' Next stack item

End

_Data Param (1) ' Reads data in reverse order,

 Local (2)                            ' starting with A@
 
 c@ = a@ + Used()                     ' Calculate next offset
 For b@ = c@-1 To a@ Step -1          ' Now place the elements 
   @(b@) = Pop()                      ' that are retrieved from the stack
 Next b@                              ' Next item

Return (c@) ' Return new offset


_Damm Param (1) ' Perform the Damm algorithm

 Local (2)                            
 c@ = 0                               ' Reset the flag
 For b@ = 0 To Len(a@) - 1            ' Check all characters in the string
   c@ = @(c@*10 + peek(a@, b@) - ord("0"))
 Next                                 ' Next character

Return (c@) ' Return Flag</lang>

Output:
  5724 is valid
  5727 is invalid
112946 is valid
112949 is invalid

0 OK, 0:984

Although the output of this version is virtually identical, it uses uBasic/4tH features consistently and is consequently much shorter. <lang>Proc _IsDamm (5724) Proc _IsDamm (5727) Proc _IsDamm (112946) Proc _IsDamm (112949)

End

_Damm

  Param (1)
  Local (1)
  b@ := "0317598642709215486342068713591750983426612304597836742095815869720134894536201794386172052581436790"
  Do Until a@ = 0                     ' until number is consumed
    Push a@ % 10 : a@ = a@ / 10       ' extract digit and put on stack
  Loop
  Do While Used ()                    ' last number retrieved?
    a@ = Peek(b@, (a@ * 10) + Pop ()) - Ord ("0")
  Loop                                ' calculate checksum

Return (a@) ' return checksum

_IsDamm ' evaluate and print checksum

 Param (1)
 Print Using "______";a@;" is ";Show (Iif (Func (_Damm (a@)), "invalid", "valid"))

Return</lang>

Visual Basic .NET

Translation of: C#

<lang vbnet>Module Module1

   ReadOnly table = {
           {0, 3, 1, 7, 5, 9, 8, 6, 4, 2},
           {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}
       }
   Function Damm(s As String) As Boolean
       Dim interim = 0
       For Each c In s
           interim = table(interim, AscW(c) - AscW("0"))
       Next
       Return interim = 0
   End Function
   Sub Main()
       Dim numbers = {5724, 5727, 112946, 112949}
       For Each number In numbers
           Dim isvalid = Damm(number.ToString())
           If isvalid Then
               Console.WriteLine("{0,6} is valid", number)
           Else
               Console.WriteLine("{0,6} is invalid", number)
           End If
       Next
   End Sub

End Module</lang>

Output:
  5724 is valid
  5727 is invalid
112946 is valid
112949 is invalid

Wren

Translation of: Go
Library: Wren-fmt

<lang ecmascript>import "/fmt" for Fmt

var table = [

   [0, 3, 1, 7, 5, 9, 8, 6, 4, 2],
   [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]

]

var damm = Fn.new { |input|

   var interim = 0
   for (c in input.bytes) interim = table[interim][c-48]
   return interim == 0

}

for (s in ["5724", "5727", "112946", "112949"]) {

   System.print("%(Fmt.s(6, s))  %(damm.call(s))")

}</lang>

Output:
  5724  true
  5727  false
112946  true
112949  false

zkl

<lang zkl>fcn damm(digits){ // digits is something that supports an iterator of integers

  var [const]  tbl=Data(0,Int,		// 10x10 byte bucket
     0, 3, 1, 7, 5, 9, 8, 6, 4, 2,
     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);
  0 == digits.reduce(fcn(interim,digit){ tbl[interim*10 + digit]  },0)

}</lang> <lang zkl>damm(List(5,7,2,4)).println(); // True damm(Data(0,Int,5,7,2,7).howza(0)).println(); // stream bytes, False damm((112946).split()).println(); // True</lang>

Output:
True
False
True