trackler 2.0.0.2 → 2.0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/common/exercises/forth/canonical-data.json +1 -1
- data/common/exercises/pangram/canonical-data.json +0 -10
- data/common/exercises/run-length-encoding/canonical-data.json +21 -11
- data/lib/trackler/version.rb +1 -1
- data/tracks/bash/SETUP.md +2 -39
- data/tracks/bash/config.json +0 -9
- data/tracks/bash/exercises/hello-world/HINTS.md +38 -0
- data/tracks/bash/exercises/hello-world/hello_world_test.sh +0 -14
- data/tracks/haskell/.travis.yml +2 -13
- data/tracks/haskell/README.md +2 -1
- data/tracks/haskell/config.json +6 -0
- data/tracks/haskell/exercises/accumulate/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/accumulate/{src/Example.hs → examples/success-standard/src/Accumulate.hs} +0 -0
- data/tracks/haskell/exercises/all-your-base/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/all-your-base/{src/Example.hs → examples/success-standard/src/Base.hs} +0 -0
- data/tracks/haskell/exercises/allergies/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/allergies/{src/Example.hs → examples/success-standard/src/Allergies.hs} +0 -0
- data/tracks/haskell/exercises/alphametics/HINTS.md +5 -0
- data/tracks/haskell/exercises/alphametics/examples/success-standard/package.yaml +18 -0
- data/tracks/haskell/exercises/alphametics/examples/success-standard/src/Alphametics.hs +116 -0
- data/tracks/haskell/exercises/alphametics/package.yaml +20 -0
- data/tracks/haskell/exercises/alphametics/src/Alphametics.hs +4 -0
- data/tracks/haskell/exercises/alphametics/stack.yaml +1 -0
- data/tracks/haskell/exercises/alphametics/test/Tests.hs +78 -0
- data/tracks/haskell/exercises/anagram/examples/{list-string → success-liststring}/package.yaml +0 -1
- data/tracks/haskell/exercises/anagram/examples/{list-string → success-liststring/src}/Anagram.hs +0 -0
- data/tracks/haskell/exercises/anagram/examples/{set-text → success-settext}/package.yaml +0 -0
- data/tracks/haskell/exercises/anagram/examples/{set-text → success-settext/src}/Anagram.hs +0 -0
- data/tracks/haskell/exercises/atbash-cipher/examples/success-standard/package.yaml +18 -0
- data/tracks/haskell/exercises/atbash-cipher/{src/Example.hs → examples/success-standard/src/Atbash.hs} +0 -0
- data/tracks/haskell/exercises/bank-account/examples/success-standard/package.yaml +18 -0
- data/tracks/haskell/exercises/bank-account/{src/Example.hs → examples/success-standard/src/BankAccount.hs} +0 -0
- data/tracks/haskell/exercises/beer-song/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/beer-song/{src/Example.hs → examples/success-standard/src/Beer.hs} +0 -0
- data/tracks/haskell/exercises/binary-search-tree/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/binary-search-tree/{src/Example.hs → examples/success-standard/src/BST.hs} +0 -0
- data/tracks/haskell/exercises/binary/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/binary/{src/Example.hs → examples/success-standard/src/Binary.hs} +0 -0
- data/tracks/haskell/exercises/bob/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/bob/{src/Example.hs → examples/success-standard/src/Bob.hs} +0 -0
- data/tracks/haskell/exercises/change/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/change/{src/Example.hs → examples/success-standard/src/Change.hs} +0 -0
- data/tracks/haskell/exercises/clock/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/clock/{src/Example.hs → examples/success-standard/src/Clock.hs} +0 -0
- data/tracks/haskell/exercises/connect/examples/success-standard/package.yaml +18 -0
- data/tracks/haskell/exercises/connect/{src/Example.hs → examples/success-standard/src/Connect.hs} +0 -0
- data/tracks/haskell/exercises/crypto-square/examples/success-standard/package.yaml +18 -0
- data/tracks/haskell/exercises/crypto-square/{src/Example.hs → examples/success-standard/src/CryptoSquare.hs} +0 -0
- data/tracks/haskell/exercises/custom-set/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/custom-set/{src/Example.hs → examples/success-standard/src/CustomSet.hs} +0 -0
- data/tracks/haskell/exercises/difference-of-squares/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/difference-of-squares/{src/Example.hs → examples/success-standard/src/Squares.hs} +0 -0
- data/tracks/haskell/exercises/etl/examples/success-standard/package.yaml +17 -0
- data/tracks/haskell/exercises/etl/{src/Example.hs → examples/success-standard/src/ETL.hs} +0 -0
- data/tracks/haskell/exercises/food-chain/examples/success-standard/package.yaml +18 -0
- data/tracks/haskell/exercises/food-chain/{src/Example.hs → examples/success-standard/src/FoodChain.hs} +0 -0
- data/tracks/haskell/exercises/forth/HINTS.md +2 -2
- data/tracks/haskell/exercises/forth/examples/success-standard/package.yaml +19 -0
- data/tracks/haskell/exercises/forth/{src/Example.hs → examples/success-standard/src/Forth.hs} +3 -3
- data/tracks/haskell/exercises/forth/package.yaml +0 -1
- data/tracks/haskell/exercises/forth/src/Forth.hs +3 -3
- data/tracks/haskell/exercises/forth/test/Tests.hs +120 -65
- data/tracks/haskell/exercises/gigasecond/examples/success-standard/package.yaml +17 -0
- data/tracks/haskell/exercises/gigasecond/{src/Example.hs → examples/success-standard/src/Gigasecond.hs} +0 -0
- data/tracks/haskell/exercises/go-counting/examples/success-standard/package.yaml +20 -0
- data/tracks/haskell/exercises/go-counting/{src/Example.hs → examples/success-standard/src/Counting.hs} +0 -0
- data/tracks/haskell/exercises/grade-school/examples/success-standard/package.yaml +18 -0
- data/tracks/haskell/exercises/grade-school/{src/Example.hs → examples/success-standard/src/School.hs} +0 -0
- data/tracks/haskell/exercises/grains/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/grains/{src/Example.hs → examples/success-standard/src/Grains.hs} +0 -0
- data/tracks/haskell/exercises/grains/test/Tests.hs +1 -2
- data/tracks/haskell/exercises/hamming/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/hamming/{src/Example.hs → examples/success-standard/src/Hamming.hs} +0 -0
- data/tracks/haskell/exercises/hexadecimal/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/hexadecimal/{src/Example.hs → examples/success-standard/src/Hexadecimal.hs} +0 -0
- data/tracks/haskell/exercises/house/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/house/{src/Example.hs → examples/success-standard/src/House.hs} +0 -0
- data/tracks/haskell/exercises/kindergarten-garden/examples/success-standard/package.yaml +19 -0
- data/tracks/haskell/exercises/kindergarten-garden/{src/Example.hs → examples/success-standard/src/Garden.hs} +0 -0
- data/tracks/haskell/exercises/largest-series-product/examples/success-standard/package.yaml +18 -0
- data/tracks/haskell/exercises/largest-series-product/{src/Example.hs → examples/success-standard/src/Series.hs} +0 -0
- data/tracks/haskell/exercises/leap/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/leap/{src/Example.hs → examples/success-standard/src/LeapYear.hs} +0 -0
- data/tracks/haskell/exercises/lens-person/examples/success-standard/package.yaml +19 -0
- data/tracks/haskell/exercises/lens-person/{src/Example.hs → examples/success-standard/src/Person.hs} +0 -0
- data/tracks/haskell/exercises/linked-list/examples/success-standard/package.yaml +18 -0
- data/tracks/haskell/exercises/linked-list/{src/Example.hs → examples/success-standard/src/Deque.hs} +0 -0
- data/tracks/haskell/exercises/list-ops/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/list-ops/{src/Example.hs → examples/success-standard/src/ListOps.hs} +0 -0
- data/tracks/haskell/exercises/luhn/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/luhn/{src/Example.hs → examples/success-standard/src/Luhn.hs} +0 -0
- data/tracks/haskell/exercises/matrix/examples/success-standard/package.yaml +17 -0
- data/tracks/haskell/exercises/matrix/{src/Example.hs → examples/success-standard/src/Matrix.hs} +0 -0
- data/tracks/haskell/exercises/meetup/examples/success-standard/package.yaml +17 -0
- data/tracks/haskell/exercises/meetup/{src/Example.hs → examples/success-standard/src/Meetup.hs} +0 -0
- data/tracks/haskell/exercises/minesweeper/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/minesweeper/{src/Example.hs → examples/success-standard/src/Minesweeper.hs} +0 -0
- data/tracks/haskell/exercises/nth-prime/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/nth-prime/{src/Example.hs → examples/success-standard/src/Prime.hs} +0 -0
- data/tracks/haskell/exercises/nucleotide-count/examples/success-standard/package.yaml +17 -0
- data/tracks/haskell/exercises/nucleotide-count/{src/Example.hs → examples/success-standard/src/DNA.hs} +0 -0
- data/tracks/haskell/exercises/ocr-numbers/examples/success-standard/package.yaml +19 -0
- data/tracks/haskell/exercises/ocr-numbers/{src/Example.hs → examples/success-standard/src/OCR.hs} +0 -0
- data/tracks/haskell/exercises/octal/examples/success-standard/package.yaml +17 -0
- data/tracks/haskell/exercises/octal/{src/Example.hs → examples/success-standard/src/Octal.hs} +0 -0
- data/tracks/haskell/exercises/palindrome-products/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/palindrome-products/{src/Example.hs → examples/success-standard/src/Palindromes.hs} +0 -0
- data/tracks/haskell/exercises/parallel-letter-frequency/examples/success-standard/package.yaml +20 -0
- data/tracks/haskell/exercises/parallel-letter-frequency/{src/Example.hs → examples/success-standard/src/Frequency.hs} +0 -0
- data/tracks/haskell/exercises/pascals-triangle/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/pascals-triangle/{src/Example.hs → examples/success-standard/src/Triangle.hs} +0 -0
- data/tracks/haskell/exercises/phone-number/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/phone-number/{src/Example.hs → examples/success-standard/src/Phone.hs} +0 -0
- data/tracks/haskell/exercises/pig-latin/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/pig-latin/{src/Example.hs → examples/success-standard/src/PigLatin.hs} +0 -0
- data/tracks/haskell/exercises/pig-latin/test/Tests.hs +2 -1
- data/tracks/haskell/exercises/pov/examples/success-standard/package.yaml +17 -0
- data/tracks/haskell/exercises/pov/{src/Example.hs → examples/success-standard/src/POV.hs} +0 -0
- data/tracks/haskell/exercises/pov/test/Tests.hs +34 -8
- data/tracks/haskell/exercises/prime-factors/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/prime-factors/{src/Example.hs → examples/success-standard/src/PrimeFactors.hs} +0 -0
- data/tracks/haskell/exercises/pythagorean-triplet/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/pythagorean-triplet/{src/Example.hs → examples/success-standard/src/Triplet.hs} +0 -0
- data/tracks/haskell/exercises/queen-attack/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/queen-attack/{src/Example.hs → examples/success-standard/src/Queens.hs} +0 -0
- data/tracks/haskell/exercises/raindrops/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/raindrops/{src/Example.hs → examples/success-standard/src/Raindrops.hs} +0 -0
- data/tracks/haskell/exercises/rna-transcription/examples/success-standard/package.yaml +18 -0
- data/tracks/haskell/exercises/rna-transcription/{src/Example.hs → examples/success-standard/src/DNA.hs} +0 -0
- data/tracks/haskell/exercises/robot-name/examples/success-standard/package.yaml +18 -0
- data/tracks/haskell/exercises/robot-name/{src/Example.hs → examples/success-standard/src/Robot.hs} +0 -0
- data/tracks/haskell/exercises/robot-simulator/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/robot-simulator/{src/Example.hs → examples/success-standard/src/Robot.hs} +0 -0
- data/tracks/haskell/exercises/roman-numerals/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/roman-numerals/{src/Example.hs → examples/success-standard/src/Roman.hs} +0 -0
- data/tracks/haskell/exercises/saddle-points/examples/success-standard/package.yaml +19 -0
- data/tracks/haskell/exercises/saddle-points/{src/Example.hs → examples/success-standard/src/Matrix.hs} +0 -0
- data/tracks/haskell/exercises/say/examples/success-standard/package.yaml +18 -0
- data/tracks/haskell/exercises/say/{src/Example.hs → examples/success-standard/src/Say.hs} +0 -0
- data/tracks/haskell/exercises/say/test/Tests.hs +4 -2
- data/tracks/haskell/exercises/scrabble-score/examples/success-standard/package.yaml +18 -0
- data/tracks/haskell/exercises/scrabble-score/{src/Example.hs → examples/success-standard/src/Scrabble.hs} +0 -0
- data/tracks/haskell/exercises/secret-handshake/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/secret-handshake/{src/Example.hs → examples/success-standard/src/SecretHandshake.hs} +0 -0
- data/tracks/haskell/exercises/series/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/series/{src/Example.hs → examples/success-standard/src/Series.hs} +0 -0
- data/tracks/haskell/exercises/sgf-parsing/examples/success-standard/package.yaml +20 -0
- data/tracks/haskell/exercises/sgf-parsing/{src/Example.hs → examples/success-standard/src/Sgf.hs} +0 -0
- data/tracks/haskell/exercises/sieve/examples/success-standard/package.yaml +18 -0
- data/tracks/haskell/exercises/sieve/{src/Example.hs → examples/success-standard/src/Sieve.hs} +0 -0
- data/tracks/haskell/exercises/simple-cipher/examples/success-standard/package.yaml +18 -0
- data/tracks/haskell/exercises/simple-cipher/{src/Example.hs → examples/success-standard/src/Cipher.hs} +0 -0
- data/tracks/haskell/exercises/simple-linked-list/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/simple-linked-list/{src/Example.hs → examples/success-standard/src/LinkedList.hs} +0 -0
- data/tracks/haskell/exercises/space-age/examples/success-double/package.yaml +0 -3
- data/tracks/haskell/exercises/space-age/examples/success-double/{SpaceAge.hs → src/SpaceAge.hs} +0 -0
- data/tracks/haskell/exercises/space-age/examples/success-rational/package.yaml +0 -3
- data/tracks/haskell/exercises/space-age/examples/success-rational/{SpaceAge.hs → src/SpaceAge.hs} +0 -0
- data/tracks/haskell/exercises/strain/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/strain/{src/Example.hs → examples/success-standard/src/Strain.hs} +0 -0
- data/tracks/haskell/exercises/sublist/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/sublist/{src/Example.hs → examples/success-standard/src/Sublist.hs} +0 -0
- data/tracks/haskell/exercises/sum-of-multiples/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/sum-of-multiples/{src/Example.hs → examples/success-standard/src/SumOfMultiples.hs} +0 -0
- data/tracks/haskell/exercises/triangle/examples/success-standard/package.yaml +18 -0
- data/tracks/haskell/exercises/triangle/{src/Example.hs → examples/success-standard/src/Triangle.hs} +0 -0
- data/tracks/haskell/exercises/trinary/examples/success-standard/package.yaml +17 -0
- data/tracks/haskell/exercises/trinary/{src/Example.hs → examples/success-standard/src/Trinary.hs} +0 -0
- data/tracks/haskell/exercises/word-count/examples/success-newtype/package.yaml +0 -2
- data/tracks/haskell/exercises/word-count/examples/success-newtype/{WordCount.hs → src/WordCount.hs} +0 -0
- data/tracks/haskell/exercises/word-count/examples/success-simple/package.yaml +0 -2
- data/tracks/haskell/exercises/word-count/examples/success-simple/{WordCount.hs → src/WordCount.hs} +0 -0
- data/tracks/haskell/exercises/wordy/examples/success-standard/package.yaml +19 -0
- data/tracks/haskell/exercises/wordy/{src/Example.hs → examples/success-standard/src/WordProblem.hs} +0 -0
- data/tracks/haskell/exercises/zebra-puzzle/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/zebra-puzzle/{src/Example.hs → examples/success-standard/src/ZebraPuzzle.hs} +0 -0
- data/tracks/haskell/exercises/zipper/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/zipper/{src/Example.hs → examples/success-standard/src/Zipper.hs} +0 -0
- data/tracks/java/config.json +7 -1
- data/tracks/java/exercises/difference-of-squares/build.gradle +17 -0
- data/tracks/java/exercises/difference-of-squares/src/example/java/.keep +0 -0
- data/tracks/java/exercises/difference-of-squares/src/example/java/Difference.java +20 -0
- data/tracks/java/exercises/difference-of-squares/src/main/java/.keep +0 -0
- data/tracks/java/exercises/difference-of-squares/src/main/java/Difference.java +5 -0
- data/tracks/java/exercises/difference-of-squares/src/test/java/DifferenceTest.java +87 -0
- data/tracks/java/exercises/settings.gradle +1 -0
- data/tracks/kotlin/docs/TESTS.md +97 -13
- data/tracks/ruby/exercises/alphametics/.version +1 -1
- data/tracks/ruby/exercises/alphametics/alphametics_test.rb +55 -45
- data/tracks/ruby/exercises/alphametics/example.rb +100 -63
- data/tracks/ruby/exercises/alphametics/example.tt +7 -6
- data/tracks/ruby/lib/alphametics_cases.rb +49 -13
- data/tracks/ruby/lib/generator.rb +2 -1
- data/tracks/rust/docs/LEARNING.md +1 -0
- data/tracks/rust/exercises/acronym/tests/acronym.rs +6 -0
- metadata +164 -80
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
4
|
@@ -3,64 +3,75 @@ gem 'minitest', '>= 5.0.0'
|
|
3
3
|
require 'minitest/autorun'
|
4
4
|
require_relative 'alphametics'
|
5
5
|
|
6
|
-
# Test data version:
|
7
|
-
# 8d8589f
|
6
|
+
# Test data version: 9dab356
|
8
7
|
class AlphameticsTest < Minitest::Test
|
9
|
-
|
8
|
+
|
9
|
+
def test_puzzle_with_three_letters
|
10
10
|
# skip
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
actual = Alphametics.new.solve('I + BB == ILL')
|
15
|
-
assert_equal(expect, actual)
|
11
|
+
input = 'I + BB == ILL'
|
12
|
+
expected = { 'B' => 9, 'I' => 1, 'L' => 0 }
|
13
|
+
assert_equal expected, Alphametics.solve(input)
|
16
14
|
end
|
17
15
|
|
18
|
-
# This test has been commented out due its long runtime.
|
19
|
-
# def test_solve_long_puzzle
|
20
|
-
# skip
|
21
|
-
# expect = {
|
22
|
-
# 'S' => 9, 'E' => 5, 'N' => 6, 'D' => 7,
|
23
|
-
# 'M' => 1, 'O' => 0, 'R' => 8, 'Y' => 2
|
24
|
-
# }
|
25
|
-
# actual = Alphametics.new.solve('SEND + MORE == MONEY')
|
26
|
-
# assert_equal(expect, actual)
|
27
|
-
# end
|
28
|
-
|
29
16
|
def test_solution_must_have_unique_value_for_each_letter
|
30
17
|
skip
|
31
|
-
|
32
|
-
|
33
|
-
assert_equal
|
18
|
+
input = 'A == B'
|
19
|
+
expected = {}
|
20
|
+
assert_equal expected, Alphametics.solve(input)
|
34
21
|
end
|
35
22
|
|
36
23
|
def test_leading_zero_solution_is_invalid
|
37
24
|
skip
|
38
|
-
|
39
|
-
|
40
|
-
assert_equal
|
25
|
+
input = 'ACA + DD == BD'
|
26
|
+
expected = {}
|
27
|
+
assert_equal expected, Alphametics.solve(input)
|
41
28
|
end
|
42
29
|
|
43
|
-
def
|
30
|
+
def test_puzzle_with_four_letters
|
44
31
|
skip
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
}
|
49
|
-
actual = Alphametics.new.solve('HE + SEES + THE == LIGHT')
|
50
|
-
assert_equal(expect, actual)
|
32
|
+
input = 'AS + A == MOM'
|
33
|
+
expected = { 'A' => 9, 'M' => 1, 'O' => 0, 'S' => 2 }
|
34
|
+
assert_equal expected, Alphametics.solve(input)
|
51
35
|
end
|
52
36
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
37
|
+
def test_puzzle_with_six_letters
|
38
|
+
skip
|
39
|
+
input = 'NO + NO + TOO == LATE'
|
40
|
+
expected = { 'A' => 0, 'E' => 2, 'L' => 1, 'N' => 7,
|
41
|
+
'O' => 4, 'T' => 9 }
|
42
|
+
assert_equal expected, Alphametics.solve(input)
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_puzzle_with_seven_letters
|
46
|
+
skip
|
47
|
+
input = 'HE + SEES + THE == LIGHT'
|
48
|
+
expected = { 'E' => 4, 'G' => 2, 'H' => 5, 'I' => 0,
|
49
|
+
'L' => 1, 'S' => 9, 'T' => 7 }
|
50
|
+
assert_equal expected, Alphametics.solve(input)
|
51
|
+
end
|
52
|
+
|
53
|
+
# The obvious algorithm can take a long time to solve this puzzle,
|
54
|
+
# but an optimised solution can solve it fairly quickly.
|
55
|
+
# (It's OK to submit your solution without getting this test to pass.)
|
56
|
+
def test_puzzle_with_eight_letters
|
57
|
+
skip
|
58
|
+
input = 'SEND + MORE == MONEY'
|
59
|
+
expected = { 'D' => 7, 'E' => 5, 'M' => 1, 'N' => 6,
|
60
|
+
'O' => 0, 'R' => 8, 'S' => 9, 'Y' => 2 }
|
61
|
+
assert_equal expected, Alphametics.solve(input)
|
62
|
+
end
|
63
|
+
|
64
|
+
# The obvious algorithm can take a long time to solve this puzzle,
|
65
|
+
# but an optimised solution can solve it fairly quickly.
|
66
|
+
# (It's OK to submit your solution without getting this test to pass.)
|
67
|
+
def test_puzzle_with_ten_letters
|
68
|
+
skip
|
69
|
+
input = 'AND + A + STRONG + OFFENSE + AS + A + GOOD == DEFENSE'
|
70
|
+
expected = { 'A' => 5, 'D' => 3, 'E' => 4, 'F' => 7,
|
71
|
+
'G' => 8, 'N' => 0, 'O' => 2, 'R' => 1,
|
72
|
+
'S' => 6, 'T' => 9 }
|
73
|
+
assert_equal expected, Alphametics.solve(input)
|
74
|
+
end
|
64
75
|
|
65
76
|
# Problems in exercism evolve over time, as we find better ways to ask
|
66
77
|
# questions.
|
@@ -78,9 +89,8 @@ class AlphameticsTest < Minitest::Test
|
|
78
89
|
#
|
79
90
|
# If you are curious, read more about constants on RubyDoc:
|
80
91
|
# http://ruby-doc.org/docs/ruby-doc-bundle/UsersGuide/rg/constants.html
|
81
|
-
|
82
92
|
def test_bookkeeping
|
83
93
|
skip
|
84
|
-
assert_equal
|
94
|
+
assert_equal 4, BookKeeping::VERSION
|
85
95
|
end
|
86
96
|
end
|
@@ -1,98 +1,135 @@
|
|
1
1
|
module BookKeeping
|
2
|
-
VERSION =
|
2
|
+
VERSION = 4
|
3
3
|
end
|
4
4
|
|
5
5
|
class Alphametics
|
6
|
-
def solve(puzzle)
|
7
|
-
letters = Hash.new(0)
|
8
|
-
puzzle.scan(/[a-zA-Z]/) { |w| letters[w] += 1 }
|
9
6
|
|
10
|
-
|
11
|
-
|
12
|
-
|
7
|
+
def self.solve(equation)
|
8
|
+
new.solve(equation)
|
9
|
+
end
|
13
10
|
|
14
|
-
|
11
|
+
def solve(equation)
|
12
|
+
@prime_solver = AlphaSolver.new(equation)
|
13
|
+
solve_using_partials
|
15
14
|
end
|
16
15
|
|
17
16
|
private
|
18
17
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
18
|
+
attr_accessor :prime_solver
|
19
|
+
|
20
|
+
def solve_using_partials
|
21
|
+
prime_solver.partial_solutions.each do |partial_solution|
|
22
|
+
sub_solver = AlphaSolver.new(prime_solver.partial_equation(partial_solution))
|
23
|
+
sub_solution = sub_solver.first_solution
|
24
|
+
return sub_solution.merge(partial_solution) if sub_solution
|
26
25
|
end
|
26
|
+
{}
|
27
27
|
end
|
28
28
|
|
29
|
-
def valid?(puzzle, letters_values)
|
30
|
-
equation = puzzle.gsub(/[a-zA-Z]/, letters_values)
|
31
|
-
Equation.new(equation).valid?
|
32
|
-
end
|
33
29
|
end
|
34
30
|
|
35
|
-
class
|
36
|
-
attr_reader :equation
|
31
|
+
class AlphaSolver
|
37
32
|
|
38
|
-
def initialize(
|
39
|
-
@
|
33
|
+
def initialize(input_equation)
|
34
|
+
@input_equation = input_equation.gsub('^', '**')
|
35
|
+
@puzzle = Puzzle.new(input_equation)
|
40
36
|
end
|
41
37
|
|
42
|
-
def
|
43
|
-
|
38
|
+
def partial_solutions
|
39
|
+
AlphaSolver.new(puzzle.simplified).all_solutions
|
40
|
+
end
|
44
41
|
|
45
|
-
|
42
|
+
def all_solutions
|
43
|
+
numeric_permutations.map { |values| result_table if solution?(values) }.compact
|
44
|
+
end
|
46
45
|
|
47
|
-
|
48
|
-
|
46
|
+
def first_solution
|
47
|
+
numeric_permutations.each { |values| return result_table if solution?(values) }
|
48
|
+
nil
|
49
|
+
end
|
49
50
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
numbers.push(token.to_i)
|
54
|
-
when '+', '-', '*', '/', '^'
|
55
|
-
calculate_last(numbers, operators) if has_precedence?(operators, token)
|
56
|
-
operators.push(token)
|
57
|
-
end
|
58
|
-
end
|
51
|
+
def partial_equation(partial_solution)
|
52
|
+
input_equation.tr(partial_solution.keys.join, partial_solution.values.join)
|
53
|
+
end
|
59
54
|
|
60
|
-
|
61
|
-
|
62
|
-
|
55
|
+
private
|
56
|
+
|
57
|
+
attr_reader :input_equation, :puzzle
|
58
|
+
attr_accessor :proposed_values
|
63
59
|
|
64
|
-
|
60
|
+
def solution?(values)
|
61
|
+
self.proposed_values = values.join
|
62
|
+
proposed_equation_qualified? && proposed_equation_evaluates?
|
65
63
|
end
|
66
64
|
|
67
|
-
|
65
|
+
def proposed_equation
|
66
|
+
input_equation.tr(puzzle_letters, proposed_values)
|
67
|
+
end
|
68
68
|
|
69
|
-
def
|
70
|
-
|
69
|
+
def numeric_permutations
|
70
|
+
puzzle.numeric_permutations
|
71
71
|
end
|
72
72
|
|
73
|
-
def
|
74
|
-
|
75
|
-
|
73
|
+
def puzzle_letters
|
74
|
+
puzzle.letters
|
75
|
+
end
|
76
76
|
|
77
|
-
|
78
|
-
|
79
|
-
prev_operator == '*' || prev_operator == '/' || prev_operator == '^'
|
80
|
-
when '*', '/'
|
81
|
-
prev_operator == '^'
|
82
|
-
else
|
83
|
-
false
|
84
|
-
end
|
77
|
+
def proposed_equation_qualified?
|
78
|
+
(proposed_equation =~ /\b0\d+/).nil?
|
85
79
|
end
|
86
80
|
|
87
|
-
def
|
88
|
-
|
89
|
-
left = numbers.pop
|
90
|
-
operator = as_ruby_operator(operators.pop)
|
91
|
-
result = left.send(operator, right)
|
92
|
-
numbers.push(result)
|
81
|
+
def proposed_equation_evaluates?
|
82
|
+
eval(proposed_equation)
|
93
83
|
end
|
94
84
|
|
95
|
-
def
|
96
|
-
|
85
|
+
def result_table
|
86
|
+
Hash[puzzle_letters.chars.zip(result_numbers)]
|
97
87
|
end
|
88
|
+
|
89
|
+
def result_numbers
|
90
|
+
proposed_values.chars.map(&:to_i)
|
91
|
+
end
|
92
|
+
|
98
93
|
end
|
94
|
+
|
95
|
+
class Puzzle
|
96
|
+
|
97
|
+
PATTERNS = {mod_10: ' % 10',
|
98
|
+
adjacent_letters: /(\b)([A-Z]{1,})([A-Z])/,
|
99
|
+
equation_left_side: /(.*)( == )/}
|
100
|
+
|
101
|
+
def initialize(string_equation)
|
102
|
+
@string_equation = string_equation
|
103
|
+
end
|
104
|
+
|
105
|
+
def letters
|
106
|
+
@letters ||= string_equation.scan(/[A-Z]/).uniq.join
|
107
|
+
end
|
108
|
+
|
109
|
+
def numeric_permutations
|
110
|
+
@numeric_permutations ||= unused_numbers.to_a.permutation(letter_count)
|
111
|
+
end
|
112
|
+
|
113
|
+
def simplified
|
114
|
+
@simplified ||= string_equation
|
115
|
+
.gsub(PATTERNS[:adjacent_letters], "\\1\\3")
|
116
|
+
.gsub(PATTERNS[:equation_left_side], "(\\1)#{PATTERNS[:mod_10]}\\2")
|
117
|
+
end
|
118
|
+
|
119
|
+
private
|
120
|
+
|
121
|
+
attr_reader :string_equation
|
122
|
+
|
123
|
+
def letter_count
|
124
|
+
@letter_count ||= letters.length
|
125
|
+
end
|
126
|
+
|
127
|
+
def unused_numbers
|
128
|
+
@unused_numbers ||= (0..9).to_a.map(&:to_s) - used_numbers
|
129
|
+
end
|
130
|
+
|
131
|
+
def used_numbers
|
132
|
+
@used_numbers ||= string_equation.gsub(PATTERNS[:mod_10], '').scan(/\d/).uniq
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
@@ -3,16 +3,17 @@ gem 'minitest', '>= 5.0.0'
|
|
3
3
|
require 'minitest/autorun'
|
4
4
|
require_relative 'alphametics'
|
5
5
|
|
6
|
-
# Test data version:
|
7
|
-
|
8
|
-
|
6
|
+
# Test data version: <%= sha1 %>
|
7
|
+
class AlphameticsTest < Minitest::Test
|
8
|
+
<% test_cases.each do |test_case| %>
|
9
|
+
|
10
|
+
<%= test_case.runtime_comment %>
|
9
11
|
def <%= test_case.test_name %>
|
10
12
|
<%= test_case.skipped %>
|
11
|
-
|
12
|
-
actual = <%= test_case.work_load %>
|
13
|
-
assert_equal(expect, actual)
|
13
|
+
<%= test_case.workload %>
|
14
14
|
end
|
15
15
|
<% end %>
|
16
|
+
|
16
17
|
<%= IO.read(XRUBY_LIB + '/bookkeeping.md') %>
|
17
18
|
def test_bookkeeping
|
18
19
|
skip
|
@@ -1,30 +1,66 @@
|
|
1
1
|
class AlphameticsCase < OpenStruct
|
2
|
-
PAIRS_PER_LINE = 4
|
3
|
-
SPACE = ->(num) { ' ' * num }
|
4
|
-
|
5
2
|
def test_name
|
6
3
|
"test_#{description.tr(' ', '_')}"
|
7
4
|
end
|
8
5
|
|
9
|
-
def
|
10
|
-
|
6
|
+
def skipped
|
7
|
+
index.zero? ? '# skip' : 'skip'
|
8
|
+
end
|
9
|
+
|
10
|
+
def input
|
11
|
+
"'#{puzzle}'"
|
11
12
|
end
|
12
13
|
|
13
14
|
def expect
|
14
|
-
|
15
|
-
|
15
|
+
expected.nil? ? {} : expected_values
|
16
|
+
end
|
17
|
+
|
18
|
+
def workload
|
19
|
+
body =
|
20
|
+
"input = %s\n" % input,
|
21
|
+
"expected = %s\n" % expect,
|
22
|
+
"assert_equal expected, Alphametics.solve(input)"
|
23
|
+
indent(body,4)
|
24
|
+
end
|
25
|
+
|
26
|
+
def runtime_comment
|
27
|
+
if slow?
|
28
|
+
comments =
|
29
|
+
'',
|
30
|
+
"# The obvious algorithm can take a long time to solve this puzzle,\n",
|
31
|
+
"# but an optimised solution can solve it fairly quickly.\n",
|
32
|
+
"# (It's OK to submit your solution without getting this test to pass.)\n"
|
33
|
+
indent(comments,2)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def slow?
|
40
|
+
(expected||{}).size > 7
|
16
41
|
end
|
17
42
|
|
18
43
|
def expected_values
|
19
|
-
"{
|
20
|
-
'%s'.prepend(SPACE[6]) %
|
21
|
-
pairs.map { |k, v| "'#{k}' => #{v}" }.join(', ')
|
22
|
-
end.join(",\n") << "\n }"
|
44
|
+
"{ #{indent(expected_values_as_lines,17)} }"
|
23
45
|
end
|
24
46
|
|
25
|
-
def
|
26
|
-
|
47
|
+
def expected_values_as_lines
|
48
|
+
lines = expected_values_as_strings.each_slice(4).map { |line| line.join(', ') }
|
49
|
+
add_trailing_comma_and_newline(lines)
|
50
|
+
end
|
51
|
+
|
52
|
+
def expected_values_as_strings
|
53
|
+
expected.sort.map { |(key,value)| "'#{key}' => #{value}" }
|
27
54
|
end
|
55
|
+
|
56
|
+
def add_trailing_comma_and_newline(lines)
|
57
|
+
lines[0...-1].map { |line| "#{line},\n" }.push(lines.last)
|
58
|
+
end
|
59
|
+
|
60
|
+
def indent(lines, spaces)
|
61
|
+
lines.join(' ' * spaces)
|
62
|
+
end
|
63
|
+
|
28
64
|
end
|
29
65
|
|
30
66
|
AlphameticsCases = proc do |data|
|
@@ -64,7 +64,8 @@ class Generator
|
|
64
64
|
|
65
65
|
def generate_test_file
|
66
66
|
File.open(path_to("#{name.gsub(/[ -]/, '_')}_test.rb"), 'w') do |f|
|
67
|
-
|
67
|
+
template = File.read(path_to('example.tt'))
|
68
|
+
f.write ERB.new(template, nil, '<>').result binding
|
68
69
|
end
|
69
70
|
end
|
70
71
|
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
* [The Rust Programming Language](http://doc.rust-lang.org/stable/book/) is a great resource for getting started with Rust as well as diving deeper into specific features of Rust.
|
4
4
|
* [Rust by Example](http://rustbyexample.com) shows you examples of the most common things you will be writing in Rust.
|
5
|
+
* [Into_rust()](http://intorust.com/) "Screencasts for learning Rust."
|
5
6
|
* [Rustlings](https://github.com/carols10cents/rustlings) "Small exercises to get you used to reading and writing Rust code."
|
6
7
|
* [#rust-beginners](https://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust-beginners) "an IRC channel that loves answering questions at any depth"
|
7
8
|
* The [Rust User Forum](http://users.rust-lang.org) answers questions of all levels
|