Przeglądaj źródła

Added exercise luhn

Piet van Dongen 11 lat temu
rodzic
commit
80ac773c19

+ 1
- 0
config.json Wyświetl plik

@@ -32,6 +32,7 @@
32 32
     "sieve",
33 33
     "simple-cipher",
34 34
     "octal",
35
+    "luhn",
35 36
     "pascals-triangle"
36 37
   ],
37 38
   "deprecated": [

+ 11
- 0
luhn/build.gradle Wyświetl plik

@@ -0,0 +1,11 @@
1
+apply plugin: "java"
2
+apply plugin: "eclipse"
3
+apply plugin: "idea"
4
+
5
+repositories {
6
+  mavenCentral()
7
+}
8
+
9
+dependencies {
10
+  testCompile "junit:junit:4.10"
11
+}

+ 90
- 0
luhn/example.java Wyświetl plik

@@ -0,0 +1,90 @@
1
+import java.util.stream.IntStream;
2
+
3
+public class Luhn {
4
+
5
+    private long number;
6
+    private long checkDigit;
7
+    private int[] addends;
8
+    private int checkSum;
9
+    private boolean isValid;
10
+
11
+    public Luhn(long number) {
12
+        this.number = number;
13
+        this.checkDigit = number % 10;
14
+        this.addends = generateAddends();
15
+        this.checkSum = IntStream.of(addends).sum();
16
+        this.isValid = checkSum % 10 == 0;
17
+    }
18
+
19
+    public long getCheckDigit() {
20
+        return checkDigit;
21
+    }
22
+
23
+    public int[] getAddends() {
24
+        return addends;
25
+    }
26
+
27
+    public int getCheckSum() {
28
+        return checkSum;
29
+    }
30
+
31
+    public boolean isValid() {
32
+        return isValid;
33
+    }
34
+
35
+    private int[] generateAddends() {
36
+        int[] reversedIntArray = splitToReversedIntArray(number);
37
+
38
+        for (int index = 1; index < reversedIntArray.length; index++) {
39
+            if (index % 2 != 0) {
40
+                reversedIntArray[index] = convertDigitForAddend(reversedIntArray[index]);
41
+            }
42
+        }
43
+
44
+        return reverseIntArray(reversedIntArray);
45
+    }
46
+
47
+    private static int[] splitToReversedIntArray(long value) {
48
+        int[] ints = new StringBuilder(Long.toString(value))
49
+                .reverse()
50
+                .toString()
51
+                .chars()
52
+                .map(x -> Character.getNumericValue(x))
53
+                .toArray();
54
+
55
+        return ints;
56
+    }
57
+
58
+    private static int convertDigitForAddend(int value) {
59
+        int doubled = value * 2;
60
+
61
+        return doubled < 10 ? doubled : doubled - 9;
62
+    }
63
+
64
+    public static long create(long number) {
65
+        long zeroCheckDigitNumber = number * 10;
66
+        Luhn luhn = new Luhn(zeroCheckDigitNumber);
67
+
68
+        if (luhn.isValid()) {
69
+            return zeroCheckDigitNumber;
70
+        }
71
+
72
+        return zeroCheckDigitNumber + createCheckDigit(luhn.getCheckSum());
73
+    }
74
+
75
+    private static int createCheckDigit(int value) {
76
+        int nearestTen = (int) (Math.ceil(value / 10.0) * 10);
77
+
78
+        return nearestTen - value;
79
+    }
80
+
81
+    private static int[] reverseIntArray(int[] array) {
82
+        int[] reversed = new int[array.length];
83
+
84
+        for (int index = 0; index < array.length; index++) {
85
+            reversed[index] = array[array.length - 1 - index];
86
+        }
87
+
88
+        return reversed;
89
+    }
90
+}

+ 0
- 0
luhn/src/main/java/.keep Wyświetl plik


+ 2
- 0
luhn/src/main/java/Luhn.java Wyświetl plik

@@ -0,0 +1,2 @@
1
+public class Luhn {
2
+}

+ 84
- 0
luhn/src/test/java/LuhnTest.java Wyświetl plik

@@ -0,0 +1,84 @@
1
+import org.junit.Test;
2
+
3
+import static org.junit.Assert.assertArrayEquals;
4
+import static org.junit.Assert.assertEquals;
5
+
6
+public class LuhnTest {
7
+
8
+    @Test
9
+    public void checkDigitIsRightMostDigit() {
10
+        Luhn luhn = new Luhn(34567);
11
+        int expectedOutput = 7;
12
+
13
+        assertEquals(expectedOutput, luhn.getCheckDigit());
14
+    }
15
+
16
+    @Test
17
+    public void addendsDoublesEveryOtherNumberFromRight() {
18
+        Luhn luhn = new Luhn(12121);
19
+        int[] expectedOutput = new int[]{1, 4, 1, 4, 1};
20
+
21
+        assertArrayEquals(expectedOutput, luhn.getAddends());
22
+    }
23
+
24
+    @Test
25
+    public void addendsSubtracts9WhenDoubledNumberIsMoreThan9() {
26
+        Luhn luhn = new Luhn(8631);
27
+        int[] expectedOutput = new int[]{7, 6, 6, 1};
28
+
29
+        assertArrayEquals(expectedOutput, luhn.getAddends());
30
+    }
31
+
32
+    @Test
33
+    public void checkSumAddsAddendsTogether1() {
34
+        Luhn luhn = new Luhn(4913);
35
+        int expectedOutput = 22;
36
+
37
+        assertEquals(expectedOutput, luhn.getCheckSum());
38
+    }
39
+
40
+    @Test
41
+    public void checkSumAddsAddendsTogether2() {
42
+        Luhn luhn = new Luhn(201773);
43
+        int expectedOutput = 21;
44
+
45
+        assertEquals(expectedOutput, luhn.getCheckSum());
46
+    }
47
+
48
+    @Test
49
+    public void numberIsValidWhenChecksumMod10IsZero1() {
50
+        Luhn luhn = new Luhn(738);
51
+        boolean expectedOutput = false;
52
+
53
+        assertEquals(expectedOutput, luhn.isValid());
54
+    }
55
+
56
+    @Test
57
+    public void numberIsValidWhenChecksumMod10IsZero2() {
58
+        Luhn luhn = new Luhn(8739567);
59
+        boolean expectedOutput = true;
60
+
61
+        assertEquals(expectedOutput, luhn.isValid());
62
+    }
63
+
64
+    @Test
65
+    public void luhnCanCreateSimpleNumbersWithValidCheckDigit() {
66
+        long expectedOutput = 1230;
67
+
68
+        assertEquals(expectedOutput, Luhn.create(123));
69
+    }
70
+
71
+    @Test
72
+    public void luhnCanCreateLargeNumbersWithValidCheckDigit() {
73
+        long expectedOutput = 8739567;
74
+
75
+        assertEquals(expectedOutput, Luhn.create(873956));
76
+    }
77
+
78
+    @Test
79
+    public void luhnCanCreateHugeNumbersWithValidCheckDigit() {
80
+        long expectedOutput = 8372637564L;
81
+
82
+        assertEquals(expectedOutput, Luhn.create(837263756));
83
+    }
84
+}