001package org.xbib.standardnumber.check; 002 003/** 004 * Verhoeff's algorithm for createChecksum computation 005 * 006 * J. Verhoeff, Error Detecting Decimal Codes, Mathematical Centre Tract 29, The Mathematical Centre, Amsterdam, 1969 007 */ 008public class DihedralGroup implements Digit { 009 010 /** 011 * dihedral addition matrix A + B = a[A][B] 012 */ 013 private static final int a[][] = { { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 014 { 1, 2, 3, 4, 0, 6, 7, 8, 9, 5 }, { 2, 3, 4, 0, 1, 7, 8, 9, 5, 6 }, 015 { 3, 4, 0, 1, 2, 8, 9, 5, 6, 7 }, { 4, 0, 1, 2, 3, 9, 5, 6, 7, 8 }, 016 { 5, 9, 8, 7, 6, 0, 4, 3, 2, 1 }, { 6, 5, 9, 8, 7, 1, 0, 4, 3, 2 }, 017 { 7, 6, 5, 9, 8, 2, 1, 0, 4, 3 }, { 8, 7, 6, 5, 9, 3, 2, 1, 0, 4 }, 018 { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 } }; 019 020 /** 021 * dihedral inverse map, A + inverse[A] = 0 022 */ 023 private static final int inverse[] = { 0, 4, 3, 2, 1, 5, 6, 7, 8, 9 }; 024 025 /** 026 * permutation weighting matrix P[position][value] 027 */ 028 private static final int p[][] = { { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 029 { 1, 5, 7, 6, 2, 8, 3, 0, 9, 4 }, { 5, 8, 0, 3, 7, 9, 6, 1, 4, 2 }, 030 { 8, 9, 1, 6, 0, 4, 3, 5, 2, 7 }, { 9, 4, 5, 3, 1, 2, 6, 8, 7, 0 }, 031 { 4, 2, 8, 6, 5, 7, 3, 9, 0, 1 }, { 2, 7, 9, 3, 8, 0, 6, 4, 1, 5 }, 032 { 7, 0, 4, 6, 9, 1, 3, 2, 5, 8 } }; 033 034 035 @Override 036 public String encode(String digits) { 037 return Integer.toString(compute(digits)) + digits; 038 } 039 040 @Override 041 public boolean verify(String digits){ 042 int check = 0; 043 for (int i = 0; i < digits.length(); ++i) { 044 check = a[check][p[i % 8][digits.charAt(i) - '0']]; 045 } 046 return check == 0; 047 } 048 049 @Override 050 public int compute(String digits) { 051 int check = 0; 052 for (int i = 0; i < digits.length(); ++i) { 053 int c = digits.charAt(i) - '0'; 054 check = a[check][p[(i + 1) % 8][c]]; 055 } 056 return inverse[check]; 057 } 058 059 @Override 060 public int getDigit(String digits) { 061 return Integer.parseInt(digits.substring(0, 1)); 062 } 063 064 @Override 065 public String getNumber(String digits) { 066 return digits.substring(1); 067 } 068}