Skip to content

Commit 8e533d2

Browse files
Boiarshinovsiriak
andauthored
Add Damm algorithm (Fixes: TheAlgorithms#2814) (TheAlgorithms#2815)
Co-authored-by: Andrii Siriak <siryaka@gmail.com>
1 parent e240c1e commit 8e533d2

File tree

1 file changed

+113
-0
lines changed

1 file changed

+113
-0
lines changed

Others/Damm.java

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
package Others;
2+
3+
import java.util.Objects;
4+
5+
/**
6+
* Damm algorithm is a check digit algorithm that detects all single-digit errors
7+
* and all adjacent transposition errors. It was presented by H. Michael Damm in 2004.
8+
* Essential part of the algorithm is a quasigroup of order 10
9+
* (i.e. having a 10 × 10 Latin square as the body of its operation table)
10+
* with the special feature of being weakly totally anti-symmetric.
11+
* Damm revealed several methods to create totally anti-symmetric quasigroups
12+
* of order 10 and gave some examples in his doctoral dissertation.
13+
*
14+
* @see <a href="https://en.wikipedia.org/wiki/Damm_algorithm">Wiki. Damm algorithm</a>
15+
*/
16+
public class Damm {
17+
18+
/**
19+
* Weakly totally anti-symmetric quasigroup of order 10.
20+
* This table is not the only possible realisation of weak totally anti-symmetric
21+
* quasigroup but the most common one (taken from Damm doctoral dissertation).
22+
* All zeros lay on the diagonal because it simplifies the check digit calculation.
23+
*/
24+
private static final byte[][] DAMM_TABLE = {
25+
{0, 3, 1, 7, 5, 9, 8, 6, 4, 2},
26+
{7, 0, 9, 2, 1, 5, 4, 8, 6, 3},
27+
{4, 2, 0, 6, 8, 7, 1, 3, 5, 9},
28+
{1, 7, 5, 0, 9, 8, 3, 4, 2, 6},
29+
{6, 1, 2, 3, 0, 4, 5, 9, 7, 8},
30+
{3, 6, 7, 4, 2, 0, 9, 5, 8, 1},
31+
{5, 8, 6, 9, 7, 2, 0, 1, 3, 4},
32+
{8, 9, 4, 5, 3, 6, 2, 0, 1, 7},
33+
{9, 4, 3, 8, 6, 1, 7, 2, 0, 5},
34+
{2, 5, 8, 1, 4, 3, 6, 7, 9, 0}
35+
};
36+
37+
/**
38+
* Check input digits by Damm algorithm.
39+
*
40+
* @param digits input to check
41+
* @return true if check was successful, false otherwise
42+
* @throws IllegalArgumentException if input parameter contains not only digits
43+
* @throws NullPointerException if input is null
44+
*/
45+
public static boolean dammCheck(String digits) {
46+
checkInput(digits);
47+
int[] numbers = toIntArray(digits);
48+
49+
int checksum = 0;
50+
for (int number : numbers) {
51+
checksum = DAMM_TABLE[checksum][number];
52+
}
53+
54+
return checksum == 0;
55+
}
56+
57+
/**
58+
* Calculate check digit for initial digits and add it tho the last position.
59+
*
60+
* @param initialDigits initial value
61+
* @return digits with the checksum in the last position
62+
* @throws IllegalArgumentException if input parameter contains not only digits
63+
* @throws NullPointerException if input is null
64+
*/
65+
public static String addDammChecksum(String initialDigits) {
66+
checkInput(initialDigits);
67+
int[] numbers = toIntArray(initialDigits);
68+
69+
int checksum = 0;
70+
for (int number : numbers) {
71+
checksum = DAMM_TABLE[checksum][number];
72+
}
73+
74+
return initialDigits + checksum;
75+
}
76+
77+
public static void main(String[] args) {
78+
System.out.println("Damm algorithm usage examples:");
79+
var validInput = "5724";
80+
var invalidInput = "5824";
81+
checkAndPrint(validInput);
82+
checkAndPrint(invalidInput);
83+
84+
System.out.println("\nCheck digit generation example:");
85+
var input = "572";
86+
generateAndPrint(input);
87+
}
88+
89+
private static void checkAndPrint(String input) {
90+
String validationResult = Damm.dammCheck(input)
91+
? "valid"
92+
: "not valid";
93+
System.out.println("Input '" + input + "' is " + validationResult);
94+
}
95+
96+
private static void generateAndPrint(String input) {
97+
String result = addDammChecksum(input);
98+
System.out.println("Generate and add checksum to initial value '" + input + "'. Result: '" + result + "'");
99+
}
100+
101+
private static void checkInput(String input) {
102+
Objects.requireNonNull(input);
103+
if (!input.matches("\\d+")) {
104+
throw new IllegalArgumentException("Input '" + input + "' contains not only digits");
105+
}
106+
}
107+
108+
private static int[] toIntArray(String string) {
109+
return string.chars()
110+
.map(i -> Character.digit(i, 10))
111+
.toArray();
112+
}
113+
}

0 commit comments

Comments
 (0)