Damm algorithm
The Damm algorithm is a checksum algorithm which detects all single digit errors and adjacent transposition errors. The task is to verify the checksum, stored as last digit of an input.
C
<lang c>#include <stdbool.h>
- include <stddef.h>
- 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>
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>
Perl 6
<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
}
- 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
<lang 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)
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