trackler 2.2.1.85 → 2.2.1.86
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/trackler/version.rb +1 -1
- data/problem-specifications/exercises/alphametics/canonical-data.json +29 -11
- data/problem-specifications/exercises/binary-search-tree/canonical-data.json +177 -0
- data/problem-specifications/package.json +2 -2
- data/problem-specifications/yarn.lock +61 -51
- data/tracks/bash/CONTRIBUTING.md +10 -6
- data/tracks/bash/README.md +1 -0
- data/tracks/bash/exercises/acronym/README.md +1 -1
- data/tracks/bash/exercises/anagram/README.md +1 -1
- data/tracks/bash/exercises/anagram/{anagram_tests.sh → anagram_test.sh} +0 -0
- data/tracks/bash/exercises/armstrong-numbers/armstrong_numbers_test.sh +25 -17
- data/tracks/bash/exercises/armstrong-numbers/example.sh +18 -12
- data/tracks/bash/exercises/atbash-cipher/README.md +1 -1
- data/tracks/bash/exercises/atbash-cipher/{atbash_cipher_tests.sh → atbash_cipher_test.sh} +0 -0
- data/tracks/bash/exercises/difference-of-squares/README.md +1 -1
- data/tracks/bash/exercises/gigasecond/README.md +1 -1
- data/tracks/bash/exercises/hamming/README.md +1 -1
- data/tracks/bash/exercises/hello-world/README.md +1 -1
- data/tracks/bash/exercises/leap/README.md +1 -1
- data/tracks/bash/exercises/luhn/README.md +1 -1
- data/tracks/bash/exercises/nucleotide-count/README.md +1 -1
- data/tracks/bash/exercises/pangram/README.md +1 -1
- data/tracks/bash/exercises/pangram/{pangram_tests.sh → pangram_test.sh} +0 -0
- data/tracks/bash/exercises/phone-number/README.md +1 -1
- data/tracks/bash/exercises/phone-number/{phone_number_tests.sh → phone_number_test.sh} +0 -0
- data/tracks/bash/exercises/raindrops/README.md +1 -1
- data/tracks/bash/exercises/rna-transcription/README.md +1 -1
- data/tracks/bash/exercises/triangle/example.sh +23 -4
- data/tracks/bash/exercises/triangle/triangle_test.sh +17 -0
- data/tracks/bash/exercises/two-fer/README.md +1 -1
- data/tracks/bash/exercises/word-count/README.md +1 -1
- data/tracks/c/config.json +11 -0
- data/tracks/c/exercises/complex-numbers/README.md +67 -0
- data/tracks/c/exercises/complex-numbers/makefile +27 -0
- data/tracks/c/exercises/complex-numbers/src/complex_numbers.c +46 -0
- data/tracks/c/exercises/complex-numbers/src/complex_numbers.h +19 -0
- data/tracks/c/exercises/complex-numbers/src/example.c +80 -0
- data/tracks/c/exercises/complex-numbers/test/test_complex_numbers.c +397 -0
- data/tracks/c/exercises/complex-numbers/test/vendor/unity.c +1300 -0
- data/tracks/c/exercises/complex-numbers/test/vendor/unity.h +274 -0
- data/tracks/c/exercises/complex-numbers/test/vendor/unity_internals.h +701 -0
- data/tracks/crystal/.github/stale.yml +18 -0
- data/tracks/csharp/exercises/bob/README.md +3 -2
- data/tracks/ecmascript/config.json +4 -4
- data/tracks/fsharp/exercises/bob/README.md +4 -2
- data/tracks/fsharp/exercises/react/ReactTest.fs +137 -74
- data/tracks/fsharp/generators/Generators.fs +76 -0
- data/tracks/go/exercises/tree-building/tree_test.go +15 -0
- data/tracks/haskell/.travis.yml +1 -1
- data/tracks/haskell/exercises/accumulate/stack.yaml +1 -1
- data/tracks/haskell/exercises/acronym/package.yaml +1 -1
- data/tracks/haskell/exercises/acronym/stack.yaml +1 -1
- data/tracks/haskell/exercises/all-your-base/package.yaml +1 -1
- data/tracks/haskell/exercises/all-your-base/stack.yaml +1 -1
- data/tracks/haskell/exercises/all-your-base/test/Tests.hs +6 -6
- data/tracks/haskell/exercises/allergies/package.yaml +1 -1
- data/tracks/haskell/exercises/allergies/stack.yaml +1 -1
- data/tracks/haskell/exercises/alphametics/stack.yaml +1 -1
- data/tracks/haskell/exercises/anagram/package.yaml +1 -1
- data/tracks/haskell/exercises/anagram/stack.yaml +1 -1
- data/tracks/haskell/exercises/atbash-cipher/package.yaml +1 -1
- data/tracks/haskell/exercises/atbash-cipher/stack.yaml +1 -1
- data/tracks/haskell/exercises/bank-account/stack.yaml +1 -1
- data/tracks/haskell/exercises/beer-song/stack.yaml +1 -1
- data/tracks/haskell/exercises/binary-search-tree/package.yaml +1 -1
- data/tracks/haskell/exercises/binary-search-tree/stack.yaml +1 -1
- data/tracks/haskell/exercises/binary-search-tree/test/Tests.hs +3 -0
- data/tracks/haskell/exercises/binary/stack.yaml +1 -1
- data/tracks/haskell/exercises/bob/package.yaml +1 -1
- data/tracks/haskell/exercises/bob/stack.yaml +1 -1
- data/tracks/haskell/exercises/bowling/stack.yaml +1 -1
- data/tracks/haskell/exercises/bracket-push/package.yaml +1 -1
- data/tracks/haskell/exercises/bracket-push/stack.yaml +1 -1
- data/tracks/haskell/exercises/change/package.yaml +1 -1
- data/tracks/haskell/exercises/change/stack.yaml +1 -1
- data/tracks/haskell/exercises/clock/stack.yaml +1 -1
- data/tracks/haskell/exercises/collatz-conjecture/package.yaml +1 -1
- data/tracks/haskell/exercises/collatz-conjecture/stack.yaml +1 -1
- data/tracks/haskell/exercises/complex-numbers/stack.yaml +1 -1
- data/tracks/haskell/exercises/connect/package.yaml +1 -1
- data/tracks/haskell/exercises/connect/stack.yaml +1 -1
- data/tracks/haskell/exercises/crypto-square/package.yaml +1 -1
- data/tracks/haskell/exercises/crypto-square/stack.yaml +1 -1
- data/tracks/haskell/exercises/custom-set/stack.yaml +1 -1
- data/tracks/haskell/exercises/diamond/package.yaml +1 -1
- data/tracks/haskell/exercises/diamond/stack.yaml +1 -1
- data/tracks/haskell/exercises/difference-of-squares/package.yaml +1 -1
- data/tracks/haskell/exercises/difference-of-squares/stack.yaml +1 -1
- data/tracks/haskell/exercises/dominoes/package.yaml +1 -1
- data/tracks/haskell/exercises/dominoes/stack.yaml +1 -1
- data/tracks/haskell/exercises/etl/stack.yaml +1 -1
- data/tracks/haskell/exercises/food-chain/stack.yaml +1 -1
- data/tracks/haskell/exercises/forth/stack.yaml +1 -1
- data/tracks/haskell/exercises/gigasecond/stack.yaml +1 -1
- data/tracks/haskell/exercises/go-counting/stack.yaml +1 -1
- data/tracks/haskell/exercises/grade-school/stack.yaml +1 -1
- data/tracks/haskell/exercises/grains/stack.yaml +1 -1
- data/tracks/haskell/exercises/hamming/stack.yaml +1 -1
- data/tracks/haskell/exercises/hello-world/stack.yaml +1 -1
- data/tracks/haskell/exercises/hexadecimal/stack.yaml +1 -1
- data/tracks/haskell/exercises/house/stack.yaml +1 -1
- data/tracks/haskell/exercises/isbn-verifier/examples/success-standard/src/IsbnVerifier.hs +1 -0
- data/tracks/haskell/exercises/isbn-verifier/package.yaml +1 -1
- data/tracks/haskell/exercises/isbn-verifier/stack.yaml +1 -1
- data/tracks/haskell/exercises/isbn-verifier/test/Tests.hs +4 -0
- data/tracks/haskell/exercises/isogram/stack.yaml +1 -1
- data/tracks/haskell/exercises/kindergarten-garden/stack.yaml +1 -1
- data/tracks/haskell/exercises/largest-series-product/stack.yaml +1 -1
- data/tracks/haskell/exercises/leap/stack.yaml +1 -1
- data/tracks/haskell/exercises/lens-person/stack.yaml +1 -1
- data/tracks/haskell/exercises/linked-list/stack.yaml +1 -1
- data/tracks/haskell/exercises/list-ops/stack.yaml +1 -1
- data/tracks/haskell/exercises/luhn/package.yaml +1 -1
- data/tracks/haskell/exercises/luhn/stack.yaml +1 -1
- data/tracks/haskell/exercises/luhn/test/Tests.hs +1 -1
- data/tracks/haskell/exercises/matrix/stack.yaml +1 -1
- data/tracks/haskell/exercises/meetup/package.yaml +1 -1
- data/tracks/haskell/exercises/meetup/stack.yaml +1 -1
- data/tracks/haskell/exercises/minesweeper/stack.yaml +1 -1
- data/tracks/haskell/exercises/nth-prime/stack.yaml +1 -1
- data/tracks/haskell/exercises/nucleotide-count/stack.yaml +1 -1
- data/tracks/haskell/exercises/ocr-numbers/stack.yaml +1 -1
- data/tracks/haskell/exercises/octal/stack.yaml +1 -1
- data/tracks/haskell/exercises/palindrome-products/stack.yaml +1 -1
- data/tracks/haskell/exercises/pangram/stack.yaml +1 -1
- data/tracks/haskell/exercises/parallel-letter-frequency/stack.yaml +1 -1
- data/tracks/haskell/exercises/pascals-triangle/stack.yaml +1 -1
- data/tracks/haskell/exercises/perfect-numbers/stack.yaml +1 -1
- data/tracks/haskell/exercises/phone-number/stack.yaml +1 -1
- data/tracks/haskell/exercises/pig-latin/stack.yaml +1 -1
- data/tracks/haskell/exercises/pov/stack.yaml +1 -1
- data/tracks/haskell/exercises/prime-factors/stack.yaml +1 -1
- data/tracks/haskell/exercises/pythagorean-triplet/stack.yaml +1 -1
- data/tracks/haskell/exercises/queen-attack/stack.yaml +1 -1
- data/tracks/haskell/exercises/rail-fence-cipher/package.yaml +1 -1
- data/tracks/haskell/exercises/rail-fence-cipher/stack.yaml +1 -1
- data/tracks/haskell/exercises/raindrops/stack.yaml +1 -1
- data/tracks/haskell/exercises/rna-transcription/package.yaml +1 -1
- data/tracks/haskell/exercises/rna-transcription/stack.yaml +1 -1
- data/tracks/haskell/exercises/rna-transcription/test/Tests.hs +0 -12
- data/tracks/haskell/exercises/robot-name/stack.yaml +1 -1
- data/tracks/haskell/exercises/robot-simulator/stack.yaml +1 -1
- data/tracks/haskell/exercises/roman-numerals/stack.yaml +1 -1
- data/tracks/haskell/exercises/rotational-cipher/stack.yaml +1 -1
- data/tracks/haskell/exercises/run-length-encoding/stack.yaml +1 -1
- data/tracks/haskell/exercises/saddle-points/stack.yaml +1 -1
- data/tracks/haskell/exercises/say/stack.yaml +1 -1
- data/tracks/haskell/exercises/scrabble-score/stack.yaml +1 -1
- data/tracks/haskell/exercises/secret-handshake/stack.yaml +1 -1
- data/tracks/haskell/exercises/series/stack.yaml +1 -1
- data/tracks/haskell/exercises/sgf-parsing/stack.yaml +1 -1
- data/tracks/haskell/exercises/sieve/stack.yaml +1 -1
- data/tracks/haskell/exercises/simple-cipher/stack.yaml +1 -1
- data/tracks/haskell/exercises/simple-linked-list/stack.yaml +1 -1
- data/tracks/haskell/exercises/space-age/stack.yaml +1 -1
- data/tracks/haskell/exercises/spiral-matrix/stack.yaml +1 -1
- data/tracks/haskell/exercises/strain/stack.yaml +1 -1
- data/tracks/haskell/exercises/sublist/stack.yaml +1 -1
- data/tracks/haskell/exercises/sum-of-multiples/stack.yaml +1 -1
- data/tracks/haskell/exercises/triangle/stack.yaml +1 -1
- data/tracks/haskell/exercises/trinary/stack.yaml +1 -1
- data/tracks/haskell/exercises/twelve-days/stack.yaml +1 -1
- data/tracks/haskell/exercises/word-count/stack.yaml +1 -1
- data/tracks/haskell/exercises/wordy/stack.yaml +1 -1
- data/tracks/haskell/exercises/zebra-puzzle/stack.yaml +1 -1
- data/tracks/haskell/exercises/zipper/stack.yaml +1 -1
- data/tracks/java/config.json +12 -0
- data/tracks/java/exercises/alphametics/.meta/src/reference/java/Alphametics.java +125 -0
- data/tracks/java/exercises/alphametics/.meta/src/reference/java/UnsolvablePuzzleException.java +2 -0
- data/tracks/java/exercises/alphametics/.meta/src/version +1 -0
- data/tracks/java/exercises/alphametics/README.md +47 -0
- data/tracks/java/exercises/alphametics/build.gradle +18 -0
- data/tracks/java/exercises/alphametics/src/main/java/.keep +0 -0
- data/tracks/java/exercises/alphametics/src/main/java/UnsolvablePuzzleException.java +2 -0
- data/tracks/java/exercises/alphametics/src/test/java/AlphameticsTest.java +150 -0
- data/tracks/java/exercises/beer-song/.meta/src/reference/java/BeerSong.java +5 -4
- data/tracks/java/exercises/beer-song/.meta/version +1 -0
- data/tracks/java/exercises/beer-song/src/test/java/BeerSongTest.java +24 -16
- data/tracks/java/exercises/binary-search/.meta/version +1 -0
- data/tracks/java/exercises/book-store/.meta/version +1 -0
- data/tracks/java/exercises/book-store/src/test/java/BookStoreTest.java +15 -8
- data/tracks/java/exercises/circular-buffer/.meta/version +1 -0
- data/tracks/java/exercises/list-ops/.meta/version +1 -1
- data/tracks/java/exercises/list-ops/src/test/java/ListOpsTest.java +1 -1
- data/tracks/java/exercises/nth-prime/.meta/version +1 -0
- data/tracks/java/exercises/settings.gradle +1 -0
- data/tracks/java/exercises/tournament/.meta/version +1 -0
- data/tracks/java/exercises/transpose/.meta/version +1 -0
- data/tracks/java/exercises/transpose/src/test/java/TransposeTest.java +29 -74
- data/tracks/java/exercises/wordy/.meta/version +1 -0
- data/tracks/javascript/.eslintignore +0 -1
- data/tracks/javascript/config.json +13 -3
- data/tracks/javascript/exercises/bowling/example.js +24 -10
- data/tracks/javascript/exercises/forth/README.md +56 -0
- data/tracks/javascript/exercises/forth/example.js +66 -0
- data/tracks/javascript/exercises/forth/forth.spec.js +259 -0
- data/tracks/lua/config.json +92 -81
- data/tracks/lua/exercises/accumulate/README.md +42 -0
- data/tracks/lua/exercises/beer-song/README.md +1 -1
- data/tracks/lua/exercises/bob/README.md +2 -0
- data/tracks/lua/exercises/crypto-square/README.md +6 -4
- data/tracks/lua/exercises/house/README.md +1 -1
- data/tracks/lua/exercises/isbn-verifier/README.md +25 -20
- data/tracks/lua/exercises/kindergarten-garden/README.md +3 -3
- data/tracks/lua/exercises/meetup/README.md +16 -12
- data/tracks/lua/exercises/nucleotide-count/README.md +2 -2
- data/tracks/lua/exercises/phone-number/README.md +1 -1
- data/tracks/lua/exercises/pov/README.md +0 -2
- data/tracks/lua/exercises/queen-attack/README.md +22 -22
- data/tracks/lua/exercises/rectangles/README.md +9 -9
- data/tracks/lua/exercises/reverse-string/README.md +23 -0
- data/tracks/lua/exercises/reverse-string/example.lua +7 -0
- data/tracks/lua/exercises/reverse-string/reverse-string_spec.lua +24 -0
- data/tracks/lua/exercises/secret-handshake/README.md +1 -1
- data/tracks/lua/exercises/space-age/README.md +1 -2
- data/tracks/lua/exercises/sum-of-multiples/README.md +3 -3
- data/tracks/perl6/exercises/two-fer/README.md +1 -1
- data/tracks/python/exercises/luhn/luhn_test.py +1 -1
- metadata +39 -6
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -40,16 +40,4 @@ cases = [ Case { description = "RNA complement of cytosine is guanine"
|
|
40
40
|
, dna = "ACGTGGTCTTAA"
|
41
41
|
, expected = Just "UGCACCAGAAUU"
|
42
42
|
}
|
43
|
-
, Case { description = "correctly handles invalid input (RNA instead of DNA)"
|
44
|
-
, dna = "U"
|
45
|
-
, expected = Nothing
|
46
|
-
}
|
47
|
-
, Case { description = "correctly handles completely invalid DNA input"
|
48
|
-
, dna = "XXX"
|
49
|
-
, expected = Nothing
|
50
|
-
}
|
51
|
-
, Case { description = "correctly handles partially invalid DNA input"
|
52
|
-
, dna = "ACGTXXXCTTAA"
|
53
|
-
, expected = Nothing
|
54
|
-
}
|
55
43
|
]
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
@@ -1 +1 @@
|
|
1
|
-
resolver: lts-
|
1
|
+
resolver: lts-10.2
|
data/tracks/java/config.json
CHANGED
@@ -612,6 +612,18 @@
|
|
612
612
|
"unlocked_by": "rotational-cipher",
|
613
613
|
"uuid": "d36ce010-210f-4e9a-9d6c-cb933e0a59af"
|
614
614
|
},
|
615
|
+
{
|
616
|
+
"core": false,
|
617
|
+
"difficulty": 6,
|
618
|
+
"slug": "alphametics",
|
619
|
+
"topics": [
|
620
|
+
"mathematics",
|
621
|
+
"logic",
|
622
|
+
"conditionals"
|
623
|
+
],
|
624
|
+
"unlocked_by": "secret-handshake",
|
625
|
+
"uuid": "0639a1f8-5af4-4877-95c1-5db8e97c30bf"
|
626
|
+
},
|
615
627
|
{
|
616
628
|
"core": false,
|
617
629
|
"difficulty": 6,
|
@@ -0,0 +1,125 @@
|
|
1
|
+
import java.util.ArrayList;
|
2
|
+
import java.util.Arrays;
|
3
|
+
import java.util.Collections;
|
4
|
+
import java.util.LinkedHashMap;
|
5
|
+
import java.util.LinkedHashSet;
|
6
|
+
import java.util.List;
|
7
|
+
import java.util.Map;
|
8
|
+
import java.util.Optional;
|
9
|
+
import java.util.Set;
|
10
|
+
import java.util.stream.Collectors;
|
11
|
+
|
12
|
+
public class Alphametics {
|
13
|
+
private final List<String> wordsToSum;
|
14
|
+
private final String wordResult;
|
15
|
+
|
16
|
+
Alphametics(String userInput) {
|
17
|
+
String[] questionAndAnswer = userInput.split("==");
|
18
|
+
wordsToSum = Arrays.stream(questionAndAnswer[0].split("\\+"))
|
19
|
+
.map(String::new)
|
20
|
+
.map(String::trim)
|
21
|
+
.collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
|
22
|
+
wordResult = questionAndAnswer[1].trim();
|
23
|
+
}
|
24
|
+
|
25
|
+
Map<Character, Integer> solve() throws UnsolvablePuzzleException {
|
26
|
+
AlphameticsRecursion solver = new AlphameticsRecursion(getDistinctCharacters());
|
27
|
+
solver.generate();
|
28
|
+
return solver.get().orElseThrow(UnsolvablePuzzleException::new);
|
29
|
+
}
|
30
|
+
|
31
|
+
/**
|
32
|
+
* Returns the list of distinct characters in this alphametic puzzle.
|
33
|
+
*/
|
34
|
+
private List<Character> getDistinctCharacters() {
|
35
|
+
Set<Character> distinctCharacters = new LinkedHashSet<>();
|
36
|
+
wordsToSum.forEach(word -> distinctCharacters.addAll(toChar(word)));
|
37
|
+
distinctCharacters.addAll(toChar(wordResult));
|
38
|
+
|
39
|
+
return new ArrayList<>(distinctCharacters);
|
40
|
+
}
|
41
|
+
|
42
|
+
private List<Character> toChar(String toChar) {
|
43
|
+
return toChar.chars()
|
44
|
+
.mapToObj(c -> (char) c)
|
45
|
+
.collect(Collectors.toList());
|
46
|
+
}
|
47
|
+
|
48
|
+
private class AlphameticsRecursion {
|
49
|
+
private final List<Character> characters;
|
50
|
+
private LinkedHashMap<Character, Integer> validPermutation;
|
51
|
+
|
52
|
+
private AlphameticsRecursion(List<Character> characters) {
|
53
|
+
this.characters = characters;
|
54
|
+
}
|
55
|
+
|
56
|
+
private void generate() {
|
57
|
+
generate(new LinkedHashMap<>(), 0, new boolean[10]);
|
58
|
+
}
|
59
|
+
|
60
|
+
private void generate(LinkedHashMap<Character, Integer> permutation, int index, boolean[] isDigitsUsed) {
|
61
|
+
// base case
|
62
|
+
if (index == characters.size()) {
|
63
|
+
if (!isLeadingDigitZero(permutation) && isSumTally(permutation)) {
|
64
|
+
validPermutation = new LinkedHashMap<>(permutation);
|
65
|
+
}
|
66
|
+
return;
|
67
|
+
}
|
68
|
+
|
69
|
+
for (int i = 0; i <= 9; i++) { // loop through digits 0 to 9
|
70
|
+
if (isDigitsUsed[i]) {
|
71
|
+
continue;
|
72
|
+
}
|
73
|
+
|
74
|
+
permutation.put(characters.get(index), i);
|
75
|
+
isDigitsUsed[i] = true;
|
76
|
+
generate(permutation, index + 1, isDigitsUsed);
|
77
|
+
isDigitsUsed[i] = false;
|
78
|
+
}
|
79
|
+
}
|
80
|
+
|
81
|
+
private Optional<LinkedHashMap<Character, Integer>> get() {
|
82
|
+
return Optional.ofNullable(validPermutation);
|
83
|
+
}
|
84
|
+
|
85
|
+
/**
|
86
|
+
* Returns true if the mapping letters to digits using {@code letterToDigit} will result in having zero as a
|
87
|
+
* leading digit.
|
88
|
+
*/
|
89
|
+
private boolean isLeadingDigitZero(Map<Character, Integer> letterToDigit) {
|
90
|
+
return letterToDigit.keySet().stream()
|
91
|
+
.filter(key -> letterToDigit.get(key) == 0) // Find the character that is mapped to digit 0
|
92
|
+
.filter(charMappedToZero -> wordResult.charAt(0) == charMappedToZero // If the first character in
|
93
|
+
// wordResult is mapped to 0
|
94
|
+
|| wordsToSum.stream() // If the first character in any of wordsToSum is mapped to 0
|
95
|
+
.map(word -> word.charAt(0))
|
96
|
+
.anyMatch(character -> character == charMappedToZero))
|
97
|
+
.count() == 1; // One letter maps to zero and is a leading character
|
98
|
+
}
|
99
|
+
|
100
|
+
/**
|
101
|
+
* Returns true if the {@code letterToDigit} solves the alphametic puzzle.
|
102
|
+
*/
|
103
|
+
private boolean isSumTally(Map<Character, Integer> letterToDigit) {
|
104
|
+
long actualSum = wordsToSum.stream()
|
105
|
+
.mapToLong(word -> mapToNumber(letterToDigit, word))
|
106
|
+
.sum();
|
107
|
+
long expectedSum = mapToNumber(letterToDigit, wordResult);
|
108
|
+
return actualSum == expectedSum;
|
109
|
+
}
|
110
|
+
|
111
|
+
/**
|
112
|
+
* Returns the long value of {@code word}, mapped using {@code letterToDigit}.
|
113
|
+
*/
|
114
|
+
private long mapToNumber(Map<Character, Integer> letterToDigit, String word) {
|
115
|
+
StringBuilder builder = new StringBuilder();
|
116
|
+
|
117
|
+
for (int i = 0; i < word.length(); i++) {
|
118
|
+
int digit = letterToDigit.get(word.charAt(i));
|
119
|
+
builder.append(digit);
|
120
|
+
}
|
121
|
+
|
122
|
+
return Long.parseLong(builder.toString());
|
123
|
+
}
|
124
|
+
}
|
125
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
1.1.0
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# Alphametics
|
2
|
+
|
3
|
+
Write a function to solve alphametics puzzles.
|
4
|
+
|
5
|
+
[Alphametics](https://en.wikipedia.org/wiki/Alphametics) is a puzzle where
|
6
|
+
letters in words are replaced with numbers.
|
7
|
+
|
8
|
+
For example `SEND + MORE = MONEY`:
|
9
|
+
|
10
|
+
```text
|
11
|
+
S E N D
|
12
|
+
M O R E +
|
13
|
+
-----------
|
14
|
+
M O N E Y
|
15
|
+
```
|
16
|
+
|
17
|
+
Replacing these with valid numbers gives:
|
18
|
+
|
19
|
+
```text
|
20
|
+
9 5 6 7
|
21
|
+
1 0 8 5 +
|
22
|
+
-----------
|
23
|
+
1 0 6 5 2
|
24
|
+
```
|
25
|
+
|
26
|
+
This is correct because every letter is replaced by a different number and the
|
27
|
+
words, translated into numbers, then make a valid sum.
|
28
|
+
|
29
|
+
Each letter must represent a different digit, and the leading digit of
|
30
|
+
a multi-digit number must not be zero.
|
31
|
+
|
32
|
+
Write a function to solve alphametics puzzles.
|
33
|
+
|
34
|
+
# Running the tests
|
35
|
+
|
36
|
+
You can run all the tests for an exercise by entering
|
37
|
+
|
38
|
+
```sh
|
39
|
+
$ gradle test
|
40
|
+
```
|
41
|
+
|
42
|
+
in your terminal.
|
43
|
+
|
44
|
+
|
45
|
+
## Submitting Incomplete Solutions
|
46
|
+
|
47
|
+
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
@@ -0,0 +1,18 @@
|
|
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.12"
|
11
|
+
}
|
12
|
+
|
13
|
+
test {
|
14
|
+
testLogging {
|
15
|
+
exceptionFormat = 'full'
|
16
|
+
events = ["passed", "failed", "skipped"]
|
17
|
+
}
|
18
|
+
}
|
File without changes
|
@@ -0,0 +1,150 @@
|
|
1
|
+
import org.junit.Ignore;
|
2
|
+
import org.junit.Rule;
|
3
|
+
import org.junit.Test;
|
4
|
+
import org.junit.rules.ExpectedException;
|
5
|
+
|
6
|
+
import java.util.Arrays;
|
7
|
+
import java.util.Collections;
|
8
|
+
import java.util.LinkedHashMap;
|
9
|
+
import java.util.List;
|
10
|
+
import java.util.Map;
|
11
|
+
|
12
|
+
import static org.hamcrest.CoreMatchers.*;
|
13
|
+
import static org.junit.Assert.*;
|
14
|
+
|
15
|
+
public class AlphameticsTest {
|
16
|
+
@Rule
|
17
|
+
public ExpectedException expectedException = ExpectedException.none();
|
18
|
+
|
19
|
+
@Test
|
20
|
+
public void testThreeLetters() throws UnsolvablePuzzleException {
|
21
|
+
LinkedHashMap<Character, Integer> expected = new LinkedHashMap<>();
|
22
|
+
expected.put('I', 1);
|
23
|
+
expected.put('B', 9);
|
24
|
+
expected.put('L', 0);
|
25
|
+
|
26
|
+
assertEquals(expected, new Alphametics("I + BB == ILL").solve());
|
27
|
+
}
|
28
|
+
|
29
|
+
@Ignore("Remove to run test")
|
30
|
+
@Test
|
31
|
+
public void testUniqueValue() throws UnsolvablePuzzleException {
|
32
|
+
expectedException.expect(UnsolvablePuzzleException.class);
|
33
|
+
new Alphametics("A == B").solve();
|
34
|
+
}
|
35
|
+
|
36
|
+
@Ignore("Remove to run test")
|
37
|
+
@Test
|
38
|
+
public void testLeadingZero() throws UnsolvablePuzzleException {
|
39
|
+
expectedException.expect(UnsolvablePuzzleException.class);
|
40
|
+
assertNull(new Alphametics("ACA + DD == BD").solve());
|
41
|
+
}
|
42
|
+
|
43
|
+
@Ignore("Remove to run test")
|
44
|
+
@Test
|
45
|
+
public void testFourLetters() throws UnsolvablePuzzleException {
|
46
|
+
LinkedHashMap<Character, Integer> expected = new LinkedHashMap<>();
|
47
|
+
expected.put('A', 9);
|
48
|
+
expected.put('S', 2);
|
49
|
+
expected.put('M', 1);
|
50
|
+
expected.put('O', 0);
|
51
|
+
|
52
|
+
assertEquals(expected, new Alphametics("AS + A == MOM").solve());
|
53
|
+
}
|
54
|
+
|
55
|
+
@Ignore("Remove to run test")
|
56
|
+
@Test
|
57
|
+
public void testSixLetters() throws UnsolvablePuzzleException {
|
58
|
+
LinkedHashMap<Character, Integer> expected = new LinkedHashMap<>();
|
59
|
+
expected.put('N', 7);
|
60
|
+
expected.put('O', 4);
|
61
|
+
expected.put('T', 9);
|
62
|
+
expected.put('L', 1);
|
63
|
+
expected.put('A', 0);
|
64
|
+
expected.put('E', 2);
|
65
|
+
|
66
|
+
assertEquals(expected, new Alphametics("NO + NO + TOO == LATE").solve());
|
67
|
+
}
|
68
|
+
|
69
|
+
@Ignore("Remove to run test")
|
70
|
+
@Test
|
71
|
+
public void testSevenLetters() throws UnsolvablePuzzleException {
|
72
|
+
LinkedHashMap<Character, Integer> expected = new LinkedHashMap<>();
|
73
|
+
expected.put('E', 4);
|
74
|
+
expected.put('G', 2);
|
75
|
+
expected.put('H', 5);
|
76
|
+
expected.put('I', 0);
|
77
|
+
expected.put('L', 1);
|
78
|
+
expected.put('S', 9);
|
79
|
+
expected.put('T', 7);
|
80
|
+
|
81
|
+
assertEquals(expected, new Alphametics("HE + SEES + THE == LIGHT").solve());
|
82
|
+
}
|
83
|
+
|
84
|
+
@Ignore("Remove to run test")
|
85
|
+
@Test
|
86
|
+
public void testEightLetters() throws UnsolvablePuzzleException {
|
87
|
+
LinkedHashMap<Character, Integer> expected = new LinkedHashMap<>();
|
88
|
+
expected.put('S', 9);
|
89
|
+
expected.put('E', 5);
|
90
|
+
expected.put('N', 6);
|
91
|
+
expected.put('D', 7);
|
92
|
+
expected.put('M', 1);
|
93
|
+
expected.put('O', 0);
|
94
|
+
expected.put('R', 8);
|
95
|
+
expected.put('Y', 2);
|
96
|
+
|
97
|
+
assertEquals(expected, new Alphametics("SEND + MORE == MONEY").solve());
|
98
|
+
}
|
99
|
+
|
100
|
+
@Ignore("Remove to run test")
|
101
|
+
@Test
|
102
|
+
public void testTenLetters() throws UnsolvablePuzzleException {
|
103
|
+
LinkedHashMap<Character, Integer> expected = new LinkedHashMap<>();
|
104
|
+
expected.put('A', 5);
|
105
|
+
expected.put('D', 3);
|
106
|
+
expected.put('E', 4);
|
107
|
+
expected.put('F', 7);
|
108
|
+
expected.put('G', 8);
|
109
|
+
expected.put('N', 0);
|
110
|
+
expected.put('O', 2);
|
111
|
+
expected.put('R', 1);
|
112
|
+
expected.put('S', 6);
|
113
|
+
expected.put('T', 9);
|
114
|
+
|
115
|
+
assertEquals(expected, new Alphametics("AND + A + STRONG + OFFENSE + AS + A + GOOD == DEFENSE").solve());
|
116
|
+
}
|
117
|
+
|
118
|
+
@Ignore("Remove to run test")
|
119
|
+
@Test
|
120
|
+
public void testTenLetters41Addends() throws UnsolvablePuzzleException {
|
121
|
+
LinkedHashMap<Character, Integer> expected = new LinkedHashMap<>();
|
122
|
+
expected.put('A', 1);
|
123
|
+
expected.put('E', 0);
|
124
|
+
expected.put('F', 5);
|
125
|
+
expected.put('H', 8);
|
126
|
+
expected.put('I', 7);
|
127
|
+
expected.put('L', 2);
|
128
|
+
expected.put('O', 6);
|
129
|
+
expected.put('R', 3);
|
130
|
+
expected.put('S', 4);
|
131
|
+
expected.put('T', 9);
|
132
|
+
|
133
|
+
assertEquals(expected, new Alphametics("THIS + A + FIRE + THEREFORE + FOR + ALL + HISTORIES + I + TELL + A + " +
|
134
|
+
"TALE + THAT + FALSIFIES + ITS + TITLE + TIS + A + LIE + THE + TALE + OF + THE + LAST + FIRE + " +
|
135
|
+
"HORSES + LATE + AFTER + THE + FIRST + FATHERS + FORESEE + THE + HORRORS + THE + LAST + FREE + " +
|
136
|
+
"TROLL + TERRIFIES + THE + HORSES + OF + FIRE + THE + TROLL + RESTS + AT + THE + HOLE + OF + " +
|
137
|
+
"LOSSES + IT + IS + THERE + THAT + SHE + STORES + ROLES + OF + LEATHERS + AFTER + SHE + SATISFIES + " +
|
138
|
+
"HER + HATE + OFF + THOSE + FEARS + A + TASTE + RISES + AS + SHE + HEARS + THE + LEAST + FAR + " +
|
139
|
+
"HORSE + THOSE + FAST + HORSES + THAT + FIRST + HEAR + THE + TROLL + FLEE + OFF + TO + THE + " +
|
140
|
+
"FOREST + THE + HORSES + THAT + ALERTS + RAISE + THE + STARES + OF + THE + OTHERS + AS + THE + " +
|
141
|
+
"TROLL + ASSAILS + AT + THE + TOTAL + SHIFT + HER + TEETH + TEAR + HOOF + OFF + TORSO + AS + THE + " +
|
142
|
+
"LAST + HORSE + FORFEITS + ITS + LIFE + THE + FIRST + FATHERS + HEAR + OF + THE + HORRORS + THEIR + " +
|
143
|
+
"FEARS + THAT + THE + FIRES + FOR + THEIR + FEASTS + ARREST + AS + THE + FIRST + FATHERS + " +
|
144
|
+
"RESETTLE + THE + LAST + OF + THE + FIRE + HORSES + THE + LAST + TROLL + HARASSES + THE + FOREST + " +
|
145
|
+
"HEART + FREE + AT + LAST + OF + THE + LAST + TROLL + ALL + OFFER + THEIR + FIRE + HEAT + TO + THE + " +
|
146
|
+
"ASSISTERS + FAR + OFF + THE + TROLL + FASTS + ITS + LIFE + SHORTER + AS + STARS + RISE + THE + " +
|
147
|
+
"HORSES + REST + SAFE + AFTER + ALL + SHARE + HOT + FISH + AS + THEIR + AFFILIATES + TAILOR + A + " +
|
148
|
+
"ROOFS + FOR + THEIR + SAFE == FORTRESSES").solve());
|
149
|
+
}
|
150
|
+
}
|