Contents

// The multiplication tablestaticintverhoeff_d[][]={{0,1,2,3,4,5,6,7,8,9},{1,2,3,4,0,6,7,8,9,5},{2,3,4,0,1,7,8,9,5,6},{3,4,0,1,2,8,9,5,6,7},{4,0,1,2,3,9,5,6,7,8},{5,9,8,7,6,0,4,3,2,1},{6,5,9,8,7,1,0,4,3,2},{7,6,5,9,8,2,1,0,4,3},{8,7,6,5,9,3,2,1,0,4},{9,8,7,6,5,4,3,2,1,0}};// The permutation tablestaticintverhoeff_p[][]={{0,1,2,3,4,5,6,7,8,9},{1,5,7,6,2,8,3,0,9,4},{5,8,0,3,7,9,6,1,4,2},{8,9,1,6,0,4,3,5,2,7},{9,4,5,3,1,2,6,8,7,0},{4,2,8,6,5,7,3,9,0,1},{2,7,9,3,8,0,6,4,1,5},{7,0,4,6,9,1,3,2,5,8}};//The inverse tablestaticintverhoeff_inv[]={0,4,3,2,1,5,6,7,8,9};//For a given number generates a Verhoeff digitstaticintgenerate_verhoeff(constchar*num){intc;intlen;c=0;len=strlen(num);for(inti=0;i<len;i++)c=verhoeff_d[c][verhoeff_p[((i+1)%8)][num[len-i-1]-'0']];returnverhoeff_inv[c];}//Validates that an entered number is Verhoeff compliant.//The check digit must be the last one.staticintvalidate_verhoeff(constchar*num){intc;intlen;c=0;len=strlen(num);for(inti=0;i<len;i++)c=verhoeff_d[c][verhoeff_p[(i%8)][num[len-i-1]-'0']];return(c==0);}

# @see <a href="http://en.wikipedia.org/wiki/Verhoeff_algorithm">More Info</a># @see <a href="http://en.wikipedia.org/wiki/Dihedral_group">Dihedral Group</a># @see <a href="http://mathworld.wolfram.com/DihedralGroupD5.html">Dihedral Group Order 10</a># @author Hermann Himmelbauerverhoeff_table_d=((0,1,2,3,4,5,6,7,8,9),(1,2,3,4,0,6,7,8,9,5),(2,3,4,0,1,7,8,9,5,6),(3,4,0,1,2,8,9,5,6,7),(4,0,1,2,3,9,5,6,7,8),(5,9,8,7,6,0,4,3,2,1),(6,5,9,8,7,1,0,4,3,2),(7,6,5,9,8,2,1,0,4,3),(8,7,6,5,9,3,2,1,0,4),(9,8,7,6,5,4,3,2,1,0))verhoeff_table_p=((0,1,2,3,4,5,6,7,8,9),(1,5,7,6,2,8,3,0,9,4),(5,8,0,3,7,9,6,1,4,2),(8,9,1,6,0,4,3,5,2,7),(9,4,5,3,1,2,6,8,7,0),(4,2,8,6,5,7,3,9,0,1),(2,7,9,3,8,0,6,4,1,5),(7,0,4,6,9,1,3,2,5,8))verhoeff_table_inv=(0,4,3,2,1,5,6,7,8,9)defcalcsum(number):"""For a given number returns a Verhoeff checksum digit"""c=0fori,iteminenumerate(reversed(str(number))):c=verhoeff_table_d[c][verhoeff_table_p[(i+1)%8][int(item)]]returnverhoeff_table_inv[c]defchecksum(number):"""For a given number generates a Verhoeff digit and returns number + digit"""c=0fori,iteminenumerate(reversed(str(number))):c=verhoeff_table_d[c][verhoeff_table_p[i%8][int(item)]]returncdefgenerateVerhoeff(number):"""For a given number returns number + Verhoeff checksum digit"""return"%s%s"%(number,calcsum(number))defvalidateVerhoeff(number):"""Validate Verhoeff checksummed number (checksum is last digit)"""returnchecksum(number)==0# Some tests and also usage examplesassertcalcsum('75872')==2assertchecksum('758722')==0assertcalcsum('12345')==1assertchecksum('123451')==0assertcalcsum('142857')==0assertchecksum('1428570')==0assertcalcsum('123456789012')==0assertchecksum('1234567890120')==0assertcalcsum('8473643095483728456789')==2assertchecksum('84736430954837284567892')==0assertgenerateVerhoeff('12345')=='123451'assertvalidateVerhoeff('123451')==TrueassertvalidateVerhoeff('122451')==FalseassertvalidateVerhoeff('128451')==False

importstd.conv;// tested with D version 2voidmain(){assert(validateVerhoeff("123451")==true);assert(validateVerhoeff("122451")==false);assert(validateVerhoeff("128451")==false);}// The multiplication tableimmutableubyte[10][10]d=[[0,1,2,3,4,5,6,7,8,9],[1,2,3,4,0,6,7,8,9,5],[2,3,4,0,1,7,8,9,5,6],[3,4,0,1,2,8,9,5,6,7],[4,0,1,2,3,9,5,6,7,8],[5,9,8,7,6,0,4,3,2,1],[6,5,9,8,7,1,0,4,3,2],[7,6,5,9,8,2,1,0,4,3],[8,7,6,5,9,3,2,1,0,4],[9,8,7,6,5,4,3,2,1,0]];// The permutation tableimmutableubyte[10][8]p=[[0,1,2,3,4,5,6,7,8,9],[1,5,7,6,2,8,3,0,9,4],[5,8,0,3,7,9,6,1,4,2],[8,9,1,6,0,4,3,5,2,7],[9,4,5,3,1,2,6,8,7,0],[4,2,8,6,5,7,3,9,0,1],[2,7,9,3,8,0,6,4,1,5],[7,0,4,6,9,1,3,2,5,8]];// The inverse tableimmutableubyte[10]inv=[0,4,3,2,1,5,6,7,8,9];publicstringgenerateVerhoeff(strings){intc;int[]a=reversedStringToIntArray(s);for(inti=0;i<a.length;i++){c=d[c][p[((i+1)%8)][a[i]]];}returnto!string(inv[c]);}publicboolvalidateVerhoeff(strings){intc;int[]a=reversedStringToIntArray(s);for(inti=0;i<a.length;i++){c=d[c][p[(i%8)][a[i]]];}return(c==0);}privateint[]reversedStringToIntArray(strings){int[]a=newint[](s.length);for(inti,ri=s.length-1;i<s.length;i++,ri--){a[i]=s[ri]-'0';}returna;}

---- PostgreSQL implementation of Verhoeff checksum.-- Based on the MS-TSQL version found at http://www.stens.ca/kb/VerhoeffCheck---- Creates a base function like the TSQL version then 2 functions to be used-- to carry out a verifiction (returning true for valid, false for not) and-- one to return the calculated checksum digit.---- Uses NUMERIC types to allow for extremely large numbers. PostgreSQL will-- automatically promote integer and bigint as needed.---- Adapted to PostgreSQL PLPGSQL by Jim Jarvie, 17 FEB 2015.---- calculateVerhoeff() returns an integer single digit which is the checksum to be used-- verifyVerhoeff() returns a boolean, true for number is valid, false for invalid--CREATEORREPLACEFUNCTIONchecksumVerhoeff(numnumeric,calcChecksumboolean)RETURNSintegerLANGUAGEplpgsqlAS$$DECLAREdCHAR(100):='0123456789123406789523401789563401289567401239567859876043216598710432765982104387659321049876543210';pCHAR(80):='01234567891576283094580379614289160435279453126870428657390127938064157046913258';invCHAR(10):='0432156789';cinteger:=0;leninteger;minteger;iinteger:=0;nVARCHAR(255);BEGIN/* Start Processing */n:=REVERSE(num::varchar);len:=LENGTH(n);WHILE(i<len)LOOPIFcalcChecksumTHEN/* Do the CalcChecksum */m:=substring(p,(((i+1)%8)*10)+substring(n,i+1,1)::integer+1,1)::integer;ELSE/* Do the Checksum */m:=substring(p,((i%8)*10)+substring(n,i+1,1)::integer+1,1)::integer;ENDIF;c:=substring(d,(c*10+m+1),1)::integer;i:=i+1;ENDLOOP;IF(calcChecksum)THEN/* Do the CalcChecksum */c:=substring(inv,c+1,1)::integer;ENDIF;RETURNc;END$$;CREATEORREPLACEFUNCTIONverifyVerhoeff(numnumeric)RETURNSbooleanLANGUAGEplpgsqlAS$$BEGINRETURN0=checksumVerhoeff(num,false);END$$;CREATEORREPLACEFUNCTIONcalculateVerhoeff(numnumeric)RETURNSintegerLANGUAGEplpgsqlAS$$BEGINRETURNchecksumVerhoeff(num,true);END$$;