trackler 2.1.0.0 → 2.1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (148) hide show
  1. checksums.yaml +4 -4
  2. data/common/exercises/connect/description.md +2 -1
  3. data/common/exercises/crypto-square/canonical-data.json +2 -2
  4. data/common/exercises/two-bucket/canonical-data.json +27 -1
  5. data/lib/trackler/version.rb +1 -1
  6. data/tracks/c/exercises/perfect-numbers/src/example.c +8 -4
  7. data/tracks/clojure/config.json +5 -0
  8. data/tracks/clojure/exercises/secret-handshake/project.clj +4 -0
  9. data/tracks/clojure/exercises/secret-handshake/src/example.clj +19 -0
  10. data/tracks/clojure/exercises/secret-handshake/test/secret_handshake_test.clj +55 -0
  11. data/tracks/cpp/.travis.yml +4 -3
  12. data/tracks/cpp/README.md +1 -1
  13. data/tracks/cpp/config.json +171 -67
  14. data/tracks/cpp/docs/ABOUT.md +2 -2
  15. data/tracks/cpp/docs/INSTALLATION.md +22 -28
  16. data/tracks/cpp/docs/TESTS.md +1 -1
  17. data/tracks/cpp/exercises/anagram/CMakeLists.txt +2 -9
  18. data/tracks/cpp/exercises/beer-song/CMakeLists.txt +2 -9
  19. data/tracks/cpp/exercises/binary/CMakeLists.txt +2 -9
  20. data/tracks/cpp/exercises/bob/CMakeLists.txt +2 -9
  21. data/tracks/cpp/exercises/clock/CMakeLists.txt +2 -9
  22. data/tracks/cpp/exercises/clock/clock_test.cpp +188 -64
  23. data/tracks/cpp/exercises/clock/example.cpp +17 -12
  24. data/tracks/cpp/exercises/clock/example.h +1 -0
  25. data/tracks/cpp/exercises/crypto-square/CMakeLists.txt +2 -9
  26. data/tracks/cpp/exercises/difference-of-squares/CMakeLists.txt +2 -9
  27. data/tracks/cpp/exercises/etl/CMakeLists.txt +2 -9
  28. data/tracks/cpp/exercises/etl/etl_test.cpp +5 -5
  29. data/tracks/cpp/exercises/food-chain/CMakeLists.txt +2 -9
  30. data/tracks/cpp/exercises/gigasecond/CMakeLists.txt +2 -9
  31. data/tracks/cpp/exercises/gigasecond/example.cpp +2 -6
  32. data/tracks/cpp/exercises/gigasecond/example.h +2 -2
  33. data/tracks/cpp/exercises/gigasecond/gigasecond_test.cpp +26 -8
  34. data/tracks/cpp/exercises/grade-school/CMakeLists.txt +2 -9
  35. data/tracks/cpp/exercises/grade-school/grade_school_test.cpp +5 -6
  36. data/tracks/cpp/exercises/grains/CMakeLists.txt +2 -9
  37. data/tracks/cpp/exercises/hamming/CMakeLists.txt +2 -9
  38. data/tracks/cpp/exercises/hello-world/CMakeLists.txt +2 -9
  39. data/tracks/cpp/exercises/hexadecimal/CMakeLists.txt +2 -9
  40. data/tracks/cpp/exercises/leap/CMakeLists.txt +2 -9
  41. data/tracks/cpp/exercises/meetup/CMakeLists.txt +2 -9
  42. data/tracks/cpp/exercises/meetup/meetup_test.cpp +1 -1
  43. data/tracks/cpp/exercises/nth-prime/CMakeLists.txt +2 -9
  44. data/tracks/cpp/exercises/nucleotide-count/CMakeLists.txt +2 -9
  45. data/tracks/cpp/exercises/nucleotide-count/nucleotide_count_test.cpp +3 -4
  46. data/tracks/cpp/exercises/phone-number/CMakeLists.txt +2 -9
  47. data/tracks/cpp/exercises/prime-factors/CMakeLists.txt +2 -9
  48. data/tracks/cpp/exercises/queen-attack/CMakeLists.txt +2 -9
  49. data/tracks/cpp/exercises/raindrops/CMakeLists.txt +2 -9
  50. data/tracks/cpp/exercises/rna-transcription/CMakeLists.txt +2 -9
  51. data/tracks/cpp/exercises/robot-name/CMakeLists.txt +2 -9
  52. data/tracks/cpp/exercises/roman-numerals/CMakeLists.txt +2 -9
  53. data/tracks/cpp/exercises/say/CMakeLists.txt +2 -9
  54. data/tracks/cpp/exercises/scrabble-score/CMakeLists.txt +2 -9
  55. data/tracks/cpp/exercises/series/CMakeLists.txt +2 -9
  56. data/tracks/cpp/exercises/series/series_test.cpp +11 -11
  57. data/tracks/cpp/exercises/sieve/CMakeLists.txt +2 -9
  58. data/tracks/cpp/exercises/space-age/CMakeLists.txt +2 -9
  59. data/tracks/cpp/exercises/sum-of-multiples/CMakeLists.txt +2 -9
  60. data/tracks/cpp/exercises/triangle/CMakeLists.txt +2 -9
  61. data/tracks/cpp/exercises/trinary/CMakeLists.txt +2 -9
  62. data/tracks/cpp/exercises/word-count/CMakeLists.txt +2 -9
  63. data/tracks/cpp/exercises/word-count/word_count_test.cpp +14 -15
  64. data/tracks/go/README.md +27 -13
  65. data/tracks/go/config.json +1 -0
  66. data/tracks/go/exercises/connect/.meta/gen.go +1 -3
  67. data/tracks/go/exercises/connect/cases_test.go +2 -1
  68. data/tracks/go/exercises/custom-set/.meta/gen.go +122 -101
  69. data/tracks/go/exercises/custom-set/cases_test.go +13 -4
  70. data/tracks/go/exercises/custom-set/custom_set_test.go +2 -2
  71. data/tracks/go/exercises/hamming/.meta/gen.go +1 -3
  72. data/tracks/go/exercises/hamming/cases_test.go +7 -1
  73. data/tracks/go/exercises/hamming/example.go +1 -1
  74. data/tracks/go/exercises/hamming/hamming_test.go +1 -1
  75. data/tracks/go/exercises/hello-world/{hello_example_test.go → example_helloworld_test.go} +0 -0
  76. data/tracks/go/exercises/house/house_test.go +8 -8
  77. data/tracks/go/exercises/meetup/.meta/gen.go +1 -3
  78. data/tracks/go/exercises/meetup/cases_test.go +2 -1
  79. data/tracks/go/exercises/palindrome-products/example.go +1 -1
  80. data/tracks/go/exercises/palindrome-products/palindrome_products_test.go +1 -1
  81. data/tracks/go/exercises/pascals-triangle/pascals_triangle_test.go +24 -4
  82. data/tracks/go/exercises/rna-transcription/.meta/gen.go +1 -3
  83. data/tracks/go/exercises/rna-transcription/cases_test.go +2 -1
  84. data/tracks/go/exercises/roman-numerals/.meta/gen.go +1 -3
  85. data/tracks/go/exercises/roman-numerals/cases_test.go +2 -1
  86. data/tracks/go/exercises/roman-numerals/example.go +1 -1
  87. data/tracks/go/exercises/transpose/.meta/gen.go +1 -3
  88. data/tracks/go/exercises/transpose/cases_test.go +2 -1
  89. data/tracks/go/exercises/transpose/transpose_test.go +5 -0
  90. data/tracks/go/exercises/word-count/.meta/gen.go +1 -3
  91. data/tracks/go/exercises/word-count/cases_test.go +2 -1
  92. data/tracks/go/gen/gen.go +3 -2
  93. data/tracks/java/config.json +5 -0
  94. data/tracks/java/exercises/saddle-points/build.gradle +17 -0
  95. data/tracks/java/exercises/saddle-points/src/example/java/Matrix.java +44 -0
  96. data/tracks/java/exercises/saddle-points/src/example/java/MatrixCoordinate.java +31 -0
  97. data/tracks/java/exercises/saddle-points/src/main/java/Matrix.java +5 -0
  98. data/tracks/java/exercises/saddle-points/src/main/java/MatrixCoordinate.java +31 -0
  99. data/tracks/java/exercises/saddle-points/src/test/java/MatrixTest.java +82 -0
  100. data/tracks/java/exercises/settings.gradle +1 -0
  101. data/tracks/javascript/.travis.yml +3 -1
  102. data/tracks/javascript/Makefile +2 -8
  103. data/tracks/javascript/SETUP.md +1 -2
  104. data/tracks/javascript/docs/INSTALLATION.md +3 -4
  105. data/tracks/javascript/docs/TESTS.md +14 -26
  106. data/tracks/javascript/exercises/hamming/example.js +7 -11
  107. data/tracks/javascript/exercises/hello-world/HINTS.md +3 -3
  108. data/tracks/javascript/exercises/robot-simulator/example.js +72 -73
  109. data/tracks/perl6/config.json +5 -0
  110. data/tracks/perl6/exercises/clock/Clock.pm6 +4 -0
  111. data/tracks/perl6/exercises/clock/Example.pm6 +12 -0
  112. data/tracks/perl6/exercises/clock/clock.t +534 -0
  113. data/tracks/perl6/exercises/clock/example.yaml +16 -0
  114. data/tracks/perl6/exercises/robot-name/Example.pm +11 -4
  115. data/tracks/php/exercises/hello-world/hello-world.php +1 -1
  116. data/tracks/php/exercises/hello-world/hello-world_test.php +1 -11
  117. data/tracks/php/exercises/robot-name/robot-name_test.php +1 -0
  118. data/tracks/purescript/config.json +7 -0
  119. data/tracks/purescript/exercises/largest-series-product/bower.json +16 -0
  120. data/tracks/purescript/exercises/largest-series-product/examples/src/LargestSeriesProduct.purs +31 -0
  121. data/tracks/purescript/exercises/largest-series-product/src/LargestSeriesProduct.purs +3 -0
  122. data/tracks/purescript/exercises/largest-series-product/test/Main.purs +73 -0
  123. data/tracks/python/exercises/sublist/sublist_test.py +94 -55
  124. data/tracks/ruby/README.md +38 -25
  125. data/tracks/ruby/exercises/hamming/example.tt +6 -4
  126. data/tracks/ruby/exercises/hamming/hamming_test.rb +4 -5
  127. data/tracks/ruby/exercises/linked-list/linked_list_test.rb +16 -0
  128. data/tracks/ruby/exercises/luhn/luhn_test.rb +5 -5
  129. data/tracks/ruby/exercises/ocr-numbers/.meta/.version +1 -0
  130. data/tracks/ruby/exercises/ocr-numbers/example.rb +42 -61
  131. data/tracks/ruby/exercises/ocr-numbers/example.tt +21 -0
  132. data/tracks/ruby/exercises/ocr-numbers/ocr_numbers_test.rb +63 -138
  133. data/tracks/ruby/lib/generator/exercise_cases.rb +43 -0
  134. data/tracks/ruby/lib/generator/underscore.rb +9 -0
  135. data/tracks/ruby/lib/hamming_cases.rb +9 -14
  136. data/tracks/ruby/lib/luhn_cases.rb +2 -18
  137. data/tracks/ruby/lib/ocr_numbers_cases.rb +20 -0
  138. data/tracks/ruby/lib/pig_latin_cases.rb +2 -12
  139. data/tracks/ruby/test/generator/underscore_test.rb +23 -0
  140. data/tracks/scala/config.json +316 -316
  141. metadata +26 -10
  142. data/tracks/cpp/exercises/etl/require_equal_containers.h +0 -88
  143. data/tracks/cpp/exercises/grade-school/require_equal_containers.h +0 -88
  144. data/tracks/cpp/exercises/nucleotide-count/require_equal_containers.h +0 -88
  145. data/tracks/cpp/exercises/series/require_equal_containers.h +0 -88
  146. data/tracks/cpp/exercises/word-count/require_equal_containers.h +0 -88
  147. data/tracks/javascript/exercises/acronym/package.json +0 -12
  148. data/tracks/javascript/package.json +0 -12
@@ -0,0 +1,16 @@
1
+ exercise: Clock
2
+ version: 1
3
+ methods: time add-minutes
4
+ plan: 54
5
+ tests: |
6
+ is ::($exercise).new(hour => .<hour>, minute => .<minute>).?time, |.<expected description> for @($c-data<cases>[0]<cases>);
7
+ for @($c-data<cases>[1]<cases>) {
8
+ my $clock = ::($exercise).new(hour => .<hour>, minute => .<minute>);
9
+ $clock.?add-minutes(.<add>);
10
+ is $clock.?time, |.<expected description>;
11
+ }
12
+ is ::($exercise).new(hour => .<clock1><hour>, minute => .<clock1><minute>).?time eq
13
+ ::($exercise).new(hour => .<clock2><hour>, minute => .<clock2><minute>).?time,
14
+ |.<expected description> for @($c-data<cases>[2]<cases>);
15
+ todo 'optional test' unless %*ENV<EXERCISM>;
16
+ is ::($exercise).new(:0hour,:0minute).?add-minutes(65).?time, '01:05', 'add-minutes method can be chained';
@@ -1,11 +1,18 @@
1
1
  unit class Robot:ver<1>;
2
2
 
3
- state %record;
4
-
5
- has Str:D $.name = self.reset-name;
3
+ subset Name of Str where * ~~ /^<[A..Z]>**2 <[0..9]>**3$/;
4
+ has Name $.name = self.reset-name;
6
5
 
7
6
  method reset-name {
8
- $!name = ('AA'..'ZZ').roll ~ ('000'..'999').roll;
7
+ state Promise:D $promise = start ('AA000'..'ZZ999').pick: *;
8
+ state Bool:D %record{Name:D};
9
+ state Int:D $i = 0;
10
+
11
+ if $promise.status ~~ 'Kept' {
12
+ ($!name = $promise.result[$i++]) or die 'All names used.';
13
+ } else {
14
+ $!name = ('A'..'Z').roll(2).join ~ (^10).roll(3).join;
15
+ }
9
16
  self.reset-name if %record{$!name}:exists;
10
17
  %record{$!name} = True;
11
18
  return $!name;
@@ -5,7 +5,7 @@
5
5
  // It's been provided as a convenience to get you started writing code faster.
6
6
  //
7
7
 
8
- function helloWorld($name = null)
8
+ function helloWorld()
9
9
  {
10
10
  //
11
11
  // YOUR CODE GOES HERE
@@ -4,18 +4,8 @@ require "hello-world.php";
4
4
 
5
5
  class HelloWorldTest extends PHPUnit\Framework\TestCase
6
6
  {
7
- public function testNoName()
7
+ public function testHelloWorld()
8
8
  {
9
9
  $this->assertEquals('Hello, World!', helloWorld());
10
10
  }
11
-
12
- public function testSampleName()
13
- {
14
- $this->assertEquals('Hello, Alice!', helloWorld('Alice'));
15
- }
16
-
17
- public function testAnotherSampleName()
18
- {
19
- $this->assertEquals('Hello, Bob!', helloWorld('Bob'));
20
- }
21
11
  }
@@ -61,6 +61,7 @@ class RobotTest extends PHPUnit\Framework\TestCase
61
61
  }
62
62
  }
63
63
 
64
+ // This test is optional.
64
65
  public function testNameUniquenessManyRobots()
65
66
  {
66
67
  $names = [];
@@ -159,6 +159,13 @@
159
159
  "topics": [
160
160
  "maps"
161
161
  ]
162
+ },
163
+ {
164
+ "slug": "largest-series-product",
165
+ "difficulty": 1,
166
+ "topics": [
167
+ "strings"
168
+ ]
162
169
  }
163
170
  ],
164
171
  "deprecated": [
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "largest-series-product",
3
+ "ignore": [
4
+ "**/.*",
5
+ "node_modules",
6
+ "bower_components",
7
+ "output"
8
+ ],
9
+ "dependencies": {
10
+ "purescript-prelude": "^3.0.0"
11
+ },
12
+ "devDependencies": {
13
+ "purescript-psci-support": "^3.0.0",
14
+ "purescript-test-unit": "^11.0.0"
15
+ }
16
+ }
@@ -0,0 +1,31 @@
1
+ module LargestSeriesProduct
2
+ ( largestProduct
3
+ ) where
4
+
5
+ import Prelude
6
+ import Data.Array (drop, length, take, (:))
7
+ import Data.Foldable (maximum, product)
8
+ import Data.Int (fromString)
9
+ import Data.Maybe (Maybe(..))
10
+ import Data.String (singleton, toCharArray)
11
+ import Data.Traversable (sequence)
12
+
13
+ spans :: forall a. Int -> Array a -> Array (Array a)
14
+ spans n a
15
+ | length a < n = []
16
+ | otherwise = take n a : spans n (drop 1 a)
17
+
18
+ toIntArray :: String -> Maybe (Array Int)
19
+ toIntArray = toCharArray
20
+ >>> map (singleton >>> fromString)
21
+ >>> sequence
22
+
23
+ largestProduct :: String -> Int -> Maybe Int
24
+ largestProduct digits span
25
+ | span == 0 = Just 1
26
+ | span < 0 = Nothing
27
+ | otherwise = do
28
+ is <- toIntArray digits
29
+ spans span is
30
+ # map product
31
+ # maximum
@@ -0,0 +1,3 @@
1
+ module LargestSeriesProduct
2
+ ( largestProduct
3
+ ) where
@@ -0,0 +1,73 @@
1
+ module Test.Main where
2
+
3
+ import Prelude
4
+ import Control.Monad.Eff (Eff)
5
+ import Data.Maybe (Maybe(..))
6
+ import Test.Unit.Assert as Assert
7
+ import Test.Unit (suite, test)
8
+ import Test.Unit.Main (runTest)
9
+ import LargestSeriesProduct (largestProduct)
10
+
11
+ main :: Eff _ Unit
12
+ main = runTest do
13
+ suite "LargestSeriesProduct.largestProduct" do
14
+
15
+ test "finds the largest product if span equals length" $
16
+ Assert.equal (Just 18)
17
+ (largestProduct "29" 2)
18
+
19
+ test "can find the largest product of 2 with numbers in order" $
20
+ Assert.equal (Just 72)
21
+ (largestProduct "0123456789" 2)
22
+
23
+ test "can find the largest product of 2" $
24
+ Assert.equal (Just 48)
25
+ (largestProduct "576802143" 2)
26
+
27
+ test "can find the largest product of 3 with numbers in order" $
28
+ Assert.equal (Just 504)
29
+ (largestProduct "0123456789" 3)
30
+
31
+ test "can find the largest product of 3" $
32
+ Assert.equal (Just 270)
33
+ (largestProduct "1027839564" 3)
34
+
35
+ test "can find the largest product of 5 with numbers in order" $
36
+ Assert.equal (Just 15120)
37
+ (largestProduct "0123456789" 5)
38
+
39
+ test "can get the largest product of a big number" $
40
+ Assert.equal (Just 23520)
41
+ (largestProduct "73167176531330624919225119674426574742355349194934" 6)
42
+
43
+ test "reports zero if the only digits are zero" $
44
+ Assert.equal (Just 0)
45
+ (largestProduct "0000" 2)
46
+
47
+ test "reports zero if all spans include zero" $
48
+ Assert.equal (Just 0)
49
+ (largestProduct "99099" 3)
50
+
51
+ test "rejects span longer than string length" $
52
+ Assert.equal Nothing
53
+ (largestProduct "123" 4)
54
+
55
+ test "reports 1 for empty string and empty product (0 span)" $
56
+ Assert.equal (Just 1)
57
+ (largestProduct "" 0)
58
+
59
+ test "reports 1 for nonempty string and empty product (0 span)" $
60
+ Assert.equal (Just 1)
61
+ (largestProduct "123" 0)
62
+
63
+ test "rejects empty string and nonzero span" $
64
+ Assert.equal Nothing
65
+ (largestProduct "" 1)
66
+
67
+ test "rejects invalid character in digits" $
68
+ Assert.equal Nothing
69
+ (largestProduct "1234a5" 2)
70
+
71
+ test "rejects negative span" $
72
+ Assert.equal Nothing
73
+ (largestProduct "12345" (-1))
@@ -3,94 +3,133 @@ import unittest
3
3
  from sublist import check_lists, SUBLIST, SUPERLIST, EQUAL, UNEQUAL
4
4
 
5
5
 
6
+ # test cases adapted from `x-common//canonical-data.json` @ version: 1.0.0
7
+
6
8
  class SublistTest(unittest.TestCase):
7
- def test_unique_return_vals(self):
9
+ def test_unique_return_values(self):
8
10
  self.assertEqual(len(set([SUBLIST, SUPERLIST, EQUAL, UNEQUAL])), 4)
9
11
 
10
12
  def test_empty_lists(self):
11
- self.assertEqual(check_lists([], []), EQUAL)
12
-
13
- def test_empty_list_within(self):
14
- self.assertEqual(check_lists([], [1, 2, 3]), SUBLIST)
15
-
16
- def test_within_empty_list(self):
17
- self.assertEqual(check_lists([1], []), SUPERLIST)
18
-
19
- def test_equal_lists(self):
20
- l1 = [0, 1, 2]
21
- l2 = [0, 1, 2]
22
- self.assertEqual(check_lists(l1, l2), EQUAL)
13
+ self.assertEqual(
14
+ check_lists([], []),
15
+ EQUAL
16
+ )
17
+
18
+ def test_empty_list_within_non_empty_list(self):
19
+ self.assertEqual(
20
+ check_lists([], [1, 2, 3]),
21
+ SUBLIST
22
+ )
23
+
24
+ def test_non_empty_list_contains_empty_list(self):
25
+ self.assertEqual(
26
+ check_lists([1, 2, 3], []),
27
+ SUPERLIST
28
+ )
29
+
30
+ def test_list_equals_itself(self):
31
+ self.assertEqual(
32
+ check_lists([1, 2, 3], [1, 2, 3]),
33
+ EQUAL
34
+ )
23
35
 
24
36
  def test_different_lists(self):
25
- l1 = list(range(1000000))
26
- l2 = list(range(1, 1000001))
27
- self.assertEqual(check_lists(l1, l2), UNEQUAL)
37
+ self.assertEqual(
38
+ check_lists([1, 2, 3], [2, 3, 4]),
39
+ UNEQUAL
40
+ )
28
41
 
29
42
  def test_false_start(self):
30
- l1 = [1, 2, 5]
31
- l2 = [0, 1, 2, 3, 1, 2, 5, 6]
32
- self.assertEqual(check_lists(l1, l2), SUBLIST)
43
+ self.assertEqual(
44
+ check_lists([1, 2, 5], [0, 1, 2, 3, 1, 2, 5, 6]),
45
+ SUBLIST
46
+ )
33
47
 
34
48
  def test_consecutive(self):
35
- l1 = [1, 1, 2]
36
- l2 = [0, 1, 1, 1, 2, 1, 2]
37
- self.assertEqual(check_lists(l1, l2), SUBLIST)
49
+ self.assertEqual(
50
+ check_lists([1, 1, 2], [0, 1, 1, 1, 2, 1, 2]),
51
+ SUBLIST
52
+ )
38
53
 
39
54
  def test_sublist_at_start(self):
40
- l1 = [0, 1, 2]
41
- l2 = [0, 1, 2, 3, 4, 5]
42
- self.assertEqual(check_lists(l1, l2), SUBLIST)
55
+ self.assertEqual(
56
+ check_lists([0, 1, 2], [0, 1, 2, 3, 4, 5]),
57
+ SUBLIST
58
+ )
43
59
 
44
60
  def test_sublist_in_middle(self):
45
- l1 = [2, 3, 4]
46
- l2 = [0, 1, 2, 3, 4, 5]
47
- self.assertEqual(check_lists(l1, l2), SUBLIST)
61
+ self.assertEqual(
62
+ check_lists([2, 3, 4], [0, 1, 2, 3, 4, 5]),
63
+ SUBLIST
64
+ )
48
65
 
49
66
  def test_sublist_at_end(self):
50
- l1 = [3, 4, 5]
51
- l2 = [0, 1, 2, 3, 4, 5]
52
- self.assertEqual(check_lists(l1, l2), SUBLIST)
67
+ self.assertEqual(
68
+ check_lists([3, 4, 5], [0, 1, 2, 3, 4, 5]),
69
+ SUBLIST
70
+ )
53
71
 
54
72
  def test_at_start_of_superlist(self):
55
- l1 = [0, 1, 2, 3, 4, 5]
56
- l2 = [0, 1, 2]
57
- self.assertEqual(check_lists(l1, l2), SUPERLIST)
73
+ self.assertEqual(
74
+ check_lists([0, 1, 2, 3, 4, 5], [0, 1, 2]),
75
+ SUPERLIST
76
+ )
58
77
 
59
78
  def test_in_middle_of_superlist(self):
60
- l1 = [0, 1, 2, 3, 4, 5]
61
- l2 = [2, 3]
62
- self.assertEqual(check_lists(l1, l2), SUPERLIST)
79
+ self.assertEqual(
80
+ check_lists([0, 1, 2, 3, 4, 5], [2, 3]),
81
+ SUPERLIST
82
+ )
63
83
 
64
84
  def test_at_end_of_superlist(self):
65
- l1 = [0, 1, 2, 3, 4, 5]
66
- l2 = [3, 4, 5]
67
- self.assertEqual(check_lists(l1, l2), SUPERLIST)
85
+ self.assertEqual(
86
+ check_lists([0, 1, 2, 3, 4, 5], [3, 4, 5]),
87
+ SUPERLIST
88
+ )
89
+
90
+ def test_first_list_missing_element_from_second_list(self):
91
+ self.assertEqual(
92
+ check_lists([1, 3], [1, 2, 3]),
93
+ UNEQUAL
94
+ )
95
+
96
+ def test_second_list_missing_element_from_first_list(self):
97
+ self.assertEqual(
98
+ check_lists([1, 2, 3], [1, 3]),
99
+ UNEQUAL
100
+ )
101
+
102
+ def test_order_matters_to_a_list(self):
103
+ self.assertEqual(
104
+ check_lists([1, 2, 3], [3, 2, 1]),
105
+ UNEQUAL
106
+ )
107
+
108
+ def test_same_digits_but_different_numbers(self):
109
+ self.assertEqual(
110
+ check_lists([1, 0, 1], [10, 1]),
111
+ UNEQUAL
112
+ )
113
+
114
+ # additional track specific test
115
+ def test_inner_spaces(self):
116
+ self.assertEqual(
117
+ check_lists(['a c'], ['a', 'c']),
118
+ UNEQUAL
119
+ )
68
120
 
121
+ # additional track specific test
69
122
  def test_large_lists(self):
70
123
  l1 = list(range(1000)) * 1000 + list(range(1000, 1100))
71
124
  l2 = list(range(900, 1050))
72
125
  self.assertEqual(check_lists(l1, l2), SUPERLIST)
73
126
 
127
+ # additional track specific test
74
128
  def test_spread_sublist(self):
75
129
  multiples_of_3 = list(range(3, 200, 3))
76
130
  multiples_of_15 = list(range(15, 200, 15))
77
131
  self.assertEqual(check_lists(multiples_of_15, multiples_of_3), UNEQUAL)
78
132
 
79
- def test_double_digits(self):
80
- l1 = [1, 0, 1]
81
- l2 = [10, 1]
82
- self.assertEqual(check_lists(l1, l2), UNEQUAL)
83
-
84
- def test_inner_spaces(self):
85
- l1 = ['a c']
86
- l2 = ['a', 'c']
87
- self.assertEqual(check_lists(l1, l2), UNEQUAL)
88
-
89
- def test_avoid_sets(self):
90
- self.assertEqual(check_lists([1, 3], [1, 2, 3]), UNEQUAL)
91
- self.assertEqual(check_lists([1, 2, 3], [1, 3]), UNEQUAL)
92
- self.assertEqual(check_lists([1, 2, 3], [3, 2, 1]), UNEQUAL)
93
-
94
133
 
95
134
  if __name__ == '__main__':
96
135
  unittest.main()
@@ -114,54 +114,48 @@ the exercise, which lives in the x-common repository.
114
114
  This change will need to be submitted as a pull request to the x-common repository. This pull
115
115
  request needs to be merged before you can regenerate the exercise.
116
116
 
117
- Changes that don't have to do directly with the test inputs and outputs, will either need to be
118
- made to `exercises/$PROBLEM/example.tt` or `lib/$PROBLEM_cases.rb`. Then you can regenerate the
119
- exercise with `bin/generate $PROBLEM`.
117
+ Changes that don't have to do directly with the test inputs and outputs, will
118
+ most likely be made to `lib/$PROBLEM_cases.rb` but may also be made to
119
+ `exercises/$PROBLEM/example.tt`. Then you can regenerate the exercise with
120
+ `bin/generate $PROBLEM`.
120
121
 
121
122
  #### Implementing a Generator
122
123
 
123
- You will need to implement three files to create a generator:
124
+ You will need to implement two files and a directory to create a generator:
124
125
 
125
- 1. `exercises/$PROBLEM/example.tt` - the Erb template for the test file, `$PROBLEM_test.rb`.
126
- 1. `exercises/$PROBLEM/.meta/.version` - used to keep track of the version of the test files as the data changes.
127
126
  1. `lib/$PROBLEM_cases.rb` - the logic for turning the data into tests.
127
+ 1. `exercises/$PROBLEM/example.tt` - the Erb template for the test file, `$PROBLEM_test.rb`.
128
+ 1. `exercises/$PROBLEM/.meta/` - metadata directory, currently contains version file
128
129
 
129
130
  You will not need to touch the top-level script, `bin/generate`.
130
131
 
131
132
  The `bin/generate` command relies on some common logic implemented in `lib/generator.rb`.
132
133
  You probably won't need to touch that, either.
133
134
 
134
- The `lib/$PROBLEM_cases.rb` file should contain a small class that wraps the JSON for a single test case:
135
+ `lib/$PROBLEM_cases.rb` contains a derived class of `ExerciseCase` (in `lib/generator/exercise_cases.rb`)
136
+ which wraps the JSON for a single test case. The default version looks something like this:
135
137
 
136
138
  ```
137
- require 'exercise_cases'
138
-
139
- class ProblemNameCase < OpenStruct
140
- def name
141
- 'test_%s' % description.gsub(/[ -]/, '_')
142
- end
139
+ class ProblemNameCase < ExerciseCase
143
140
 
144
141
  def workload
145
142
  # Example workload:
146
- "assert #{expected.inspect}, Problem.call(#{input.inspect})"
143
+ "#{assert} Problem.call(#{input.inspect})"
147
144
  end
148
145
 
149
- def skipped
150
- index.zero? ? '# skip' : 'skip'
151
- end
152
146
  end
153
147
  ```
154
148
 
155
- Instead of `ProblemName` use the name of the actual problem. This is important, since
149
+ Instead of `ProblemName` use the CamelCased name of the actual problem. This is important, since
156
150
  the generator script will infer the name of the class from the argument that is passed.
157
151
 
158
- This class must implement the following methods:
159
-
160
- - `name` - Returns the name of the test (i.e `test_one_equals_one`)
161
- - `workload` - Returns the main syntax for the test. This includes the assertion and any setup required for the test. This will vary depending on the test generator and its underlying implementation
162
- - `skipped` - Returns skip syntax (i.e. `skip` or `# skip`)
152
+ This class must provide the methods used by `example.tt`. The base class provides methods
153
+ for the default template for everything except `workload`.
163
154
 
164
- Beyond that, you can implement any helper methods that you need.
155
+ `workload` generates the code for the body of a test, including the assertion
156
+ and any setup required. The base class provides a variety of assertion and
157
+ helper methods. Beyond that, you can implement any helper methods that you need
158
+ as private methods in your derived class. See below for more information about [the intention of workload](#workload-philosophy)
165
159
 
166
160
  Below this class, implement a small loop that will generate all the test cases by reading the
167
161
  `canonical-data.json` file, and looping through the test cases.
@@ -198,7 +192,8 @@ end
198
192
 
199
193
  Finally, you need to create a text template, `example.tt`, as the bases for the test suite.
200
194
 
201
- Start with the following boilerplate, and adjust as necessary:
195
+ Start with the following boilerplate, and adjust as necessary. Remember, however, to strive
196
+ to keep logic out of views.
202
197
 
203
198
  ```
204
199
  #!/usr/bin/env ruby
@@ -216,12 +211,30 @@ class ProblemNameTest < Minitest::Test
216
211
 
217
212
  <% end %>
218
213
  <%= IO.read(XRUBY_LIB + '/bookkeeping.md') %>
214
+
219
215
  def test_bookkeeping
220
216
  skip
221
217
  assert_equal <%= version %>, BookKeeping::VERSION
222
218
  end
223
219
  end
224
220
  ```
221
+ ### Workload philosophy.
222
+
223
+ Prioritize educational value over expert comprehension and make sure that
224
+ things are clear to people who may not be familiar with Minitest and even Ruby.
225
+
226
+ Provide the information the student needs to derive the code to pass the test
227
+ in a clear and consistent manner. Illustrate the purpose of the individual
228
+ elements of the assertion by using meaningful variable names.
229
+
230
+ Example output from the `workload` method:
231
+ ```ruby
232
+ detector = Anagram.new('allergy')
233
+ anagrams = detector.match(["gallery", "ballerina", "regally", "clergy", "largely", "leading"])
234
+ expected = ["gallery", "largely", "regally"]
235
+ assert_equal expected, anagrams.sort
236
+ ```
237
+
225
238
 
226
239
  ## Pull Requests
227
240