< Algorithm Implementation < Checksums

C

/// <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

"""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
This article is issued from Wikibooks. The text is licensed under Creative Commons - Attribution - Sharealike. Additional terms may apply for the media files.