# Algorithm Implementation/Checksums/Damm Algorithm

## Perl

```const my @map => (
[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],
);

sub check_damm {
my \$d = 0;
\$d = \$map[\$d][\$_] for split //,pop;
\$d ? 0 : 1;
}

sub damm_digit {
my \$d = 0;
\$d = \$map[\$d][\$_] for split //,pop;
\$d;
}
```

## C

```/// <summary>
/// The Damm check digit
/// </summary>
/// <remarks>
/// The array could be substituted with another
/// appropriate weak totally anti-symmetric quasigroup.
/// This would affect the check digit.
/// </remarks>
char Lookup(char* number)
{
const char table[]=
"0317598642"
"7092154863"
"4206871359"
"1750983426"
"6123045978"
"3674209581"
"5869720134"
"8945362017"
"9438617205"
"2581436790";
char interim='0';
char* p;
for(p=number;*p!='\0';++p){
if((unsigned char)(*p-'0')>9)
return '-'; //minus sign indicates an error: character is not a digit
interim=table[(*p-'0')+(interim-'0')*10];
}
return interim;
}

char CalculateCheckDigit(char* numberWithoutCheckDigit)
{
return Lookup(numberWithoutCheckDigit);
}

typedef int BOOL;
BOOL IsCheckDigitValid(char* numberWithCheckDigit)
{
return Lookup(numberWithCheckDigit)=='0';
}
```

## Python

```"""Damm algorithm decimal check digit

For reference see https://en.wikipedia.org/wiki/Damm_algorithm
"""

# we use the matrix given in the WP article because it's a good one
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)
)

def encode(number):
number = str(number)
interim = 0

for digit in number:
interim = matrix[interim][int(digit)]

return interim

def check(number):
return encode(number) == 0

if __name__ == '__main__':
# quick sanity checking
assert encode(572) == 4 # from wikipedia
assert check(5724)
assert encode('43881234567') == 9 # hand-computed
```

## C#

```    /// <summary>
/// The implementation of the damm algorithm based on the details on https://en.wikipedia.org/wiki/Damm_algorithm
/// </summary>
public static class DammAlgorithm
{
/// <summary>
/// The quasigroup table from https://en.wikipedia.org/wiki/Damm_algorithm
/// </summary>

static int[,] matrix = new 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}
};

/// <summary>
/// Calculate the checksum digit from provided number
/// </summary>
/// <param name="number">the number</param>
/// <returns>Damm checksum</returns>
public static int CalculateCheckSum(string number)
{
var numbers = (from n in number select int.Parse(n.ToString()));
int interim = 0;
var en = numbers.GetEnumerator();
while (en.MoveNext())
{
interim = matrix[interim, en.Current];
}
return interim;
}

/// <summary>
/// Calculate the checksum digit from provided number
/// </summary>
/// <param name="number">the number</param>
/// <returns>Damm checksum</returns>
public static int CalculateCheckSum(int number)
{
return CalculateCheckSum(number.ToString());
}

/// <summary>
/// Calculate the checksum digit from provided number
/// </summary>
/// <param name="number">the number</param>
/// <returns>Damm checksum</returns>
public static int CalculateCheckSum(long number)
{
return CalculateCheckSum(number.ToString());
}

/// <summary>
/// Calculate the checksum digit from provided number and return the full number with the checksum
/// </summary>
/// <param name="number">the number</param>
/// <returns>full number with the Damm checksum</returns>
public static string GenerateCheckSum(string number)
{
var checkSumNumber = CalculateCheckSum(number);
return number + checkSumNumber.ToString();
}

/// <summary>
/// Calculate the checksum digit from provided number and return the full number with the checksum
/// </summary>
/// <param name="number">the number</param>
/// <returns>full number with the Damm checksum</returns>
public static int GenerateCheckSum(int number)
{
var checkSumNumber = CalculateCheckSum(number);
return (number * 10) + checkSumNumber;
}

/// <summary>
/// Calculate the checksum digit from provided number and return the full number with the checksum
/// </summary>
/// <param name="number">the number</param>
/// <returns>full number with the Damm checksum</returns>
public static long GenerateCheckSum(long number)
{
var checkSumNumber = CalculateCheckSum(number);
return (number * 10) + checkSumNumber;
}

/// <summary>
/// validates the number using the last digit as the Damm checksum
/// </summary>
/// <param name="number">the number to check</param>
/// <returns>True if valid; otherwise false</returns>
public static bool Validate(string number)
{
return CalculateCheckSum(number) == 0;
}

/// <summary>
/// validates the number using the last digit as the Damm checksum
/// </summary>
/// <param name="number">the number to check</param>
/// <returns>True if valid; otherwise false</returns>
public static bool Validate(int number)
{
return CalculateCheckSum(number) == 0;
}

/// <summary>
/// validates the number using the last digit as the Damm checksum
/// </summary>
/// <param name="number">the number to check</param>
/// <returns>True if valid; otherwise false</returns>
public static bool Validate(long number)
{
return CalculateCheckSum(number) == 0;
}
}
```

## VBA

```    ' <summary>
' The implementation of the damm algorithm based on the details on https://en.wikipedia.org/wiki/Damm_algorithm
' </summary>
Public Function Encode(ByVal number As String) As Byte
Dim i       As Long
Dim interim As Byte
Dim matrix

matrix = 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)) _

For i = 1 To Len(number)
interim = matrix(interim)(CByte(Mid(number, i, 1)))
Next i
Encode = interim
End Function

Public Function check(ByVal number as String) as Boolean
If encode(number) = 0 then
check = True
Else
check = False
End if
End Function
```

## PHP

```<?php
/**
* The implementation of the damm algorithm based on the details on https://en.wikipedia.org/wiki/Damm_algorithm
*
* Class DammAlgorithm
*/
class DammAlgorithm
{
/**
* The quasigroup table from http://www.md-software.de/math/DAMM_Quasigruppen.txt
*
* @var \$matrix array
*/
protected static \$matrix = 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),
);

/**
* Calculate the checksum digit from provided number
*
* @param \$number
* @return int
*/
public static function encode(\$number) {
/* @var \$interim int */
\$interim = 0;
/* @var \$i int */
for (\$i=0; \$i<strlen(\$number); \$i++) {
\$interim = self::\$matrix[\$interim][\$number[\$i]];
}

return \$interim;
}

/**
* Checks the checksum digit from provided number
*
* @param \$number
* @return bool
*/
public static function check(\$number) {
return (0 == self::encode(\$number));
}
}
```

## Java

```/**
* The implementation of the damm algorithm based on the details on https://en.wikipedia.org/wiki/Damm_algorithm
*/
public class Damm10ChecksumDigit {

/**
* The quasigroup table from https://en.wikipedia.org/wiki/Damm_algorithm
*/
private static int[][] matrix = new 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 } };

/**
* Calculate the checksum digit from provided number
*
* @param number
* @return calculated Damm checksum digit
*/
public static int calculateCheckSumDigit(String number) {

int interim = 0;
for (int index = 0; index < number.length(); index++) {
char currCh = number.charAt(index);
if (! Character.isDigit(currCh)) {
throw new RuntimeException(number + " is not a valid number");
}

int currentIndex = currCh - 48;
interim = matrix[interim][currentIndex];
}

return interim;
}

/**
* Calculate the checksum digit from provided number
* @param number
* @return calculated Damm checksum digit
*/
public static int calculateCheckSumDigit(int number) {
return calculateCheckSumDigit(String.valueOf(number));
}

/**
* Calculate the checksum digit from provided number
* @param number
* @return calculated Damm checksum digit
*/
public static int calculateCheckSumDigit(long number) {
return calculateCheckSumDigit(String.valueOf(number));
}

/**
* Calculate the checksum digit from provided number and return the full
* number with the checksum
* @param number
* @return full number with the Damm checksum
*/
public static String generateCheckSum(String number) {
int checkSumDigit = calculateCheckSumDigit(number);

return number + String.valueOf(checkSumDigit);
}

/**
* Calculate the checksum digit from provided number and return the full
* number with the checksum
* @param number
* @return full number with the Damm checksum
*/
public static int generateCheckSum(int number) {
int checkSumDigit = calculateCheckSumDigit(number);
return (number * 10) + checkSumDigit;
}

/**
* Calculate the checksum digit from provided number and return the full
* number with the checksum
* @param number
* @return full number with the Damm checksum
*/
public static long generateCheckSum(long number) {
int checkSumNumber = calculateCheckSumDigit(number);
return (number * 10) + checkSumNumber;
}

/**
* validates the number using the last digit as the Damm checksum
*
* @param number
* @return True if valid; otherwise false
*/
public static boolean validate(String number) {
return calculateCheckSumDigit(number) == 0;
}

/**
* validates the number using the last digit as the Damm checksum
*
* @param number
* @return True if valid; otherwise false
*/
public static boolean validate(int number) {
return calculateCheckSumDigit(number) == 0;
}

/**
* validates the number using the last digit as the Damm checksum
*
* @param number
* @return True if valid; otherwise false
*/
public static boolean validate(long number) {
return calculateCheckSumDigit(number) == 0;
}
}
```

## Ruby

```module Damm
# See https://en.wikipedia.org/wiki/Damm_algorithm
TABLE=["0317598642","7092154863","4206871359","1750983426","6123045978",
"3674209581","5869720134","8945362017","9438617205","2581436790"]

def lookup number
number.to_s.each_char.inject(0) {|m,v|
TABLE[m][v.to_i].to_i
}
end
def check number
lookup(number.to_i/10)==number%10
end
def generate number
number.to_i*10+lookup(number.to_i)
end
extend(Damm)
end
```

## Scala

```object Damm {

private val matrix = 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)
)

/**
* Calculates the checksum from the provided string
* @param str a string, only the numerics will be calculated
* @return
*/
def encode(str: String): Int = {

@tailrec def fn(interim: Int, idx: Int): Int = {
if (idx >= str.length) {
interim
} else {
val c = str.charAt(idx)
// only push numerics...
fn( if (c.isDigit) matrix(interim)(c - 48) else interim, idx + 1)
}
}

fn (0, 0)
}

/**
* Decorates the string with the checksum
* @param str
* @return
*/
def apply(str: String): String = str + encode(str).toString

/**
* Unapply method returning the string without the checksum if it matches otherwise None
* @param str
* @return
*/
def unapply(str: String): Option[String] =
if (isValid(str)) Some(str.substring(0, str.length - 1)) else None

/**
* Determines if the string contains a valid checksum
* @param str
* @return
*/
def isValid(str: String): Boolean = encode(str) == 0

}
```

## JavaScript

```// Taken from Wikipedia: Damm_Algorithm
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]
];

function calc(number) {
var str = number + '',
sum = 0;
for (var i = 0; i < str.length; ++i) {
sum = table[sum][str[i]];
}
return sum;
}

function check(number) {
return calc(number) == 0;
}
```

## Elixir

```defmodule Damm do
@table [
"0317598642","7092154863","4206871359","1750983426","6123045978",
"3674209581","5869720134","8945362017","9438617205","2581436790"
]
|> Enum.map( fn cs ->
to_charlist( cs )
|> Enum.map( &(&1-?0) )
|> List.to_tuple
end )
|> List.to_tuple

def table, do: @table
def lookup(number) do
number
|> Integer.digits
|> Enum.reduce( 0, fn d,a ->
elem(@table,a) |> elem(d)
end)
end
def check(number) do
lookup(Integer.floor_div(number,10))==Integer.mod(number,10)
end
def generate(number) do
number*10 + lookup( number )
end
end
```

## Pascal

```const
Damm_Array: array[0..9, 0..9] of 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)
);

var
interim: Byte;
i: Integer;
begin
interim := 0;
for i := 1 to Length(Num) do
interim := Damm_Array[interim, Ord(Num[i]) - \$30];
Result := Char(interim + \$30);
end;

begin
if Num <> '' then
Result := Num + CalcDamm(Num)
else
Result := '';
end;

begin
if num <> '' then
Result := CalcDamm(Num) = '0'
else
Result := False;
end;
```

## R

```Damm_digit <- function(IDvar){
nondig <- simpleError("The function Damm_digit() stopped, because the submitted ID vector contains non-digit characters.")
if (sum(grepl("[^0-9]", IDvar)) > 0) stop(nondig)

quasigroup <- matrix( data  = as.integer(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))
, ncol  = 10
, byrow = TRUE
)

IDdig     <- lapply(strsplit(as.character(IDvar), ""), as.integer)
chk_digit <- integer()
for (i in seq_along(IDdig)){
tmp_digit <- 0
for (j in IDdig[[i]]) tmp_digit <- quasigroup[tmp_digit+1, j+1]
chk_digit <- c(chk_digit, tmp_digit)
}
return(chk_digit)
}

Damm_encode <- function(IDvar) IDvar * 10 + Damm_digit(IDvar)

Damm_check  <- function(IDvar) IDvar %% 10 == Damm_digit(trunc(IDvar/10))
```