Algorithm Implementation/Checksums/Damm Algorithm

From Wikibooks, open books for an open world
Jump to: navigation, search

C[edit]

/// <summary>
/// The Damm check digit
/// For more information cf. http://en.wikipedia.org/wiki/Damm_algorithm
/// </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[edit]

"""Damm algorithm decimal check digit
 
For reference see http://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#[edit]

    /// <summary>
    /// The implementation of the damm algorithm based on the details on http://en.wikipedia.org/wiki/Damm_algorithm
    /// </summary>
    public static class DammAlgorithm
    {
        /// <summary>
        /// The quasigroup table from http://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[edit]

    ' <summary>
    ' The implementation of the damm algorithm based on the details on http://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[edit]

<?php
/**
 * The implementation of the damm algorithm based on the details on http://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[edit]

/**
 * The implementation of the damm algorithm based on the details on http://en.wikipedia.org/wiki/Damm_algorithm
 */
public class Damm10ChecksumDigit {
 
    /**
     * The quasigroup table from http://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[edit]

module Damm
  # See http://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