# Algorithm Implementation/Checksums/Damm Algorithm

ナビゲーションに移動 検索に移動

## 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 calcDamm(basenumber) { // Damm Algorighm
var s,damm;
damm = 0;
s = String(basenumber);
for (var i=0; i<s.length; ++i) {
damm = table[damm][s.charAt(i)];
}
return damm;
}

function checkDamm(number) {
return calcDamm(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
```