trackler 2.0.0.8 → 2.0.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (226) hide show
  1. checksums.yaml +4 -4
  2. data/common/exercises/bob/canonical-data.json +1 -20
  3. data/common/exercises/raindrops/canonical-data.json +18 -0
  4. data/common/exercises/sublist/canonical-data.json +5 -0
  5. data/lib/trackler/version.rb +1 -1
  6. data/tracks/clojure/config.json +5 -0
  7. data/tracks/clojure/exercises/pig-latin/project.clj +4 -0
  8. data/tracks/clojure/exercises/pig-latin/src/example.clj +49 -0
  9. data/tracks/clojure/exercises/pig-latin/test/pig_latin_test.clj +92 -0
  10. data/tracks/clojure/exercises/robot-name/src/example.clj +8 -11
  11. data/tracks/clojure/exercises/robot-name/test/robot_name_test.clj +23 -18
  12. data/tracks/crystal/config.json +6 -0
  13. data/tracks/crystal/exercises/acronym/spec/acronym_spec.cr +7 -7
  14. data/tracks/crystal/exercises/forth/spec/forth_spec.cr +198 -0
  15. data/tracks/crystal/exercises/forth/src/example.cr +187 -0
  16. data/tracks/crystal/exercises/hello-world/spec/hello_world_spec.cr +3 -3
  17. data/tracks/crystal/src/generator/exercises/acronym.cr +1 -1
  18. data/tracks/crystal/src/generator/exercises/exercise_generator.cr +3 -2
  19. data/tracks/crystal/src/generator/exercises/forth.cr +56 -0
  20. data/tracks/crystal/src/generator/exercises/templates/example.tt +2 -2
  21. data/tracks/crystal/src/generator/spec/exercise_generator_spec.cr +5 -3
  22. data/tracks/csharp/exercises/wordy/WordyTest.cs +2 -2
  23. data/tracks/elixir/config.json +83 -70
  24. data/tracks/fsharp/exercises/wordy/WordyTest.fs +1 -1
  25. data/tracks/go/config.json +28 -3
  26. data/tracks/go/exercises/all-your-base/all_your_base_test.go +185 -0
  27. data/tracks/go/exercises/all-your-base/example.go +60 -0
  28. data/tracks/go/exercises/isogram/example.go +15 -0
  29. data/tracks/go/exercises/isogram/isogram_test.go +50 -0
  30. data/tracks/go/exercises/ledger/ledger.go +2 -2
  31. data/tracks/go/exercises/pangram/example.go +32 -0
  32. data/tracks/go/exercises/pangram/pangram_test.go +43 -0
  33. data/tracks/go/exercises/protein-translation/example.go +59 -0
  34. data/tracks/go/exercises/protein-translation/protein_translation_test.go +69 -0
  35. data/tracks/go/exercises/tree-building/tree_building.go +1 -1
  36. data/tracks/go/exercises/twelve-days/example.go +57 -0
  37. data/tracks/go/exercises/twelve-days/twelve_days_test.go +79 -0
  38. data/tracks/haskell/.travis.yml +13 -8
  39. data/tracks/haskell/config.json +6 -0
  40. data/tracks/haskell/exercises/accumulate/stack.yaml +1 -1
  41. data/tracks/haskell/exercises/all-your-base/stack.yaml +1 -1
  42. data/tracks/haskell/exercises/allergies/stack.yaml +1 -1
  43. data/tracks/haskell/exercises/alphametics/stack.yaml +1 -1
  44. data/tracks/haskell/exercises/anagram/stack.yaml +1 -1
  45. data/tracks/haskell/exercises/atbash-cipher/stack.yaml +1 -1
  46. data/tracks/haskell/exercises/bank-account/stack.yaml +1 -1
  47. data/tracks/haskell/exercises/beer-song/stack.yaml +1 -1
  48. data/tracks/haskell/exercises/binary/stack.yaml +1 -1
  49. data/tracks/haskell/exercises/binary-search-tree/stack.yaml +1 -1
  50. data/tracks/haskell/exercises/bob/stack.yaml +1 -1
  51. data/tracks/haskell/exercises/bowling/HINTS.md +19 -0
  52. data/tracks/haskell/exercises/bowling/examples/success-standard/package.yaml +16 -0
  53. data/tracks/haskell/exercises/bowling/examples/success-standard/src/Bowling.hs +84 -0
  54. data/tracks/haskell/exercises/bowling/package.yaml +19 -0
  55. data/tracks/haskell/exercises/bowling/src/Bowling.hs +9 -0
  56. data/tracks/haskell/exercises/bowling/stack.yaml +1 -0
  57. data/tracks/haskell/exercises/bowling/test/Tests.hs +143 -0
  58. data/tracks/haskell/exercises/change/stack.yaml +1 -1
  59. data/tracks/haskell/exercises/clock/stack.yaml +1 -1
  60. data/tracks/haskell/exercises/connect/stack.yaml +1 -1
  61. data/tracks/haskell/exercises/crypto-square/stack.yaml +1 -1
  62. data/tracks/haskell/exercises/custom-set/stack.yaml +1 -1
  63. data/tracks/haskell/exercises/difference-of-squares/stack.yaml +1 -1
  64. data/tracks/haskell/exercises/dominoes/stack.yaml +1 -1
  65. data/tracks/haskell/exercises/etl/stack.yaml +1 -1
  66. data/tracks/haskell/exercises/food-chain/stack.yaml +1 -1
  67. data/tracks/haskell/exercises/forth/stack.yaml +1 -1
  68. data/tracks/haskell/exercises/gigasecond/stack.yaml +1 -1
  69. data/tracks/haskell/exercises/go-counting/stack.yaml +1 -1
  70. data/tracks/haskell/exercises/grade-school/stack.yaml +1 -1
  71. data/tracks/haskell/exercises/grains/stack.yaml +1 -1
  72. data/tracks/haskell/exercises/hamming/stack.yaml +1 -1
  73. data/tracks/haskell/exercises/hexadecimal/stack.yaml +1 -1
  74. data/tracks/haskell/exercises/house/stack.yaml +1 -1
  75. data/tracks/haskell/exercises/kindergarten-garden/stack.yaml +1 -1
  76. data/tracks/haskell/exercises/largest-series-product/stack.yaml +1 -1
  77. data/tracks/haskell/exercises/leap/stack.yaml +1 -1
  78. data/tracks/haskell/exercises/lens-person/stack.yaml +1 -1
  79. data/tracks/haskell/exercises/linked-list/stack.yaml +1 -1
  80. data/tracks/haskell/exercises/list-ops/stack.yaml +1 -1
  81. data/tracks/haskell/exercises/luhn/stack.yaml +1 -1
  82. data/tracks/haskell/exercises/matrix/stack.yaml +1 -1
  83. data/tracks/haskell/exercises/meetup/stack.yaml +1 -1
  84. data/tracks/haskell/exercises/minesweeper/stack.yaml +1 -1
  85. data/tracks/haskell/exercises/nth-prime/stack.yaml +1 -1
  86. data/tracks/haskell/exercises/nucleotide-count/stack.yaml +1 -1
  87. data/tracks/haskell/exercises/ocr-numbers/stack.yaml +1 -1
  88. data/tracks/haskell/exercises/octal/stack.yaml +1 -1
  89. data/tracks/haskell/exercises/palindrome-products/stack.yaml +1 -1
  90. data/tracks/haskell/exercises/parallel-letter-frequency/stack.yaml +1 -1
  91. data/tracks/haskell/exercises/pascals-triangle/stack.yaml +1 -1
  92. data/tracks/haskell/exercises/phone-number/stack.yaml +1 -1
  93. data/tracks/haskell/exercises/pig-latin/stack.yaml +1 -1
  94. data/tracks/haskell/exercises/pov/stack.yaml +1 -1
  95. data/tracks/haskell/exercises/prime-factors/stack.yaml +1 -1
  96. data/tracks/haskell/exercises/pythagorean-triplet/stack.yaml +1 -1
  97. data/tracks/haskell/exercises/queen-attack/stack.yaml +1 -1
  98. data/tracks/haskell/exercises/raindrops/stack.yaml +1 -1
  99. data/tracks/haskell/exercises/rna-transcription/stack.yaml +1 -1
  100. data/tracks/haskell/exercises/robot-name/stack.yaml +1 -1
  101. data/tracks/haskell/exercises/robot-simulator/stack.yaml +1 -1
  102. data/tracks/haskell/exercises/roman-numerals/stack.yaml +1 -1
  103. data/tracks/haskell/exercises/saddle-points/stack.yaml +1 -1
  104. data/tracks/haskell/exercises/say/stack.yaml +1 -1
  105. data/tracks/haskell/exercises/scrabble-score/stack.yaml +1 -1
  106. data/tracks/haskell/exercises/secret-handshake/stack.yaml +1 -1
  107. data/tracks/haskell/exercises/series/stack.yaml +1 -1
  108. data/tracks/haskell/exercises/sgf-parsing/stack.yaml +1 -1
  109. data/tracks/haskell/exercises/sieve/stack.yaml +1 -1
  110. data/tracks/haskell/exercises/simple-cipher/stack.yaml +1 -1
  111. data/tracks/haskell/exercises/simple-linked-list/stack.yaml +1 -1
  112. data/tracks/haskell/exercises/space-age/stack.yaml +1 -1
  113. data/tracks/haskell/exercises/strain/stack.yaml +1 -1
  114. data/tracks/haskell/exercises/sublist/stack.yaml +1 -1
  115. data/tracks/haskell/exercises/sum-of-multiples/stack.yaml +1 -1
  116. data/tracks/haskell/exercises/triangle/stack.yaml +1 -1
  117. data/tracks/haskell/exercises/trinary/stack.yaml +1 -1
  118. data/tracks/haskell/exercises/word-count/stack.yaml +1 -1
  119. data/tracks/haskell/exercises/wordy/stack.yaml +1 -1
  120. data/tracks/haskell/exercises/zebra-puzzle/stack.yaml +1 -1
  121. data/tracks/haskell/exercises/zipper/stack.yaml +1 -1
  122. data/tracks/java/config.json +13 -1
  123. data/tracks/java/exercises/etl/src/main/java/Etl.java +3 -3
  124. data/tracks/java/exercises/hello-world/GETTING_STARTED.md +1 -1
  125. data/tracks/java/exercises/hello-world/src/main/java/HelloWorld.java +3 -3
  126. data/tracks/java/exercises/minesweeper/build.gradle +17 -0
  127. data/tracks/java/exercises/minesweeper/src/example/java/MinesweeperBoard.java +111 -0
  128. data/tracks/java/exercises/minesweeper/src/main/java/MinesweeperBoard.java +5 -0
  129. data/tracks/java/exercises/minesweeper/src/test/java/MinesweeperBoardTest.java +295 -0
  130. data/tracks/java/exercises/nucleotide-count/src/test/java/NucleotideTest.java +67 -67
  131. data/tracks/java/exercises/series/build.gradle +18 -0
  132. data/tracks/java/exercises/series/src/example/java/Series.java +39 -0
  133. data/tracks/java/exercises/series/src/main/java/.keep +0 -0
  134. data/tracks/java/exercises/series/src/main/java/Series.java +3 -0
  135. data/tracks/java/exercises/series/src/test/java/.keep +0 -0
  136. data/tracks/java/exercises/series/src/test/java/SeriesTest.java +154 -0
  137. data/tracks/java/exercises/settings.gradle +2 -0
  138. data/tracks/javascript/exercises/custom-set/custom-set.spec.js +130 -84
  139. data/tracks/javascript/exercises/custom-set/example-gen.js +200 -0
  140. data/tracks/ocaml/Makefile +5 -1
  141. data/tracks/ocaml/config.json +2 -1
  142. data/tracks/ocaml/exercises/anagram/test.ml +35 -24
  143. data/tracks/ocaml/exercises/bob/example.ml +1 -1
  144. data/tracks/ocaml/exercises/bob/test.ml +53 -40
  145. data/tracks/ocaml/exercises/hamming/test.ml +41 -31
  146. data/tracks/ocaml/exercises/raindrops/test.ml +38 -39
  147. data/tracks/ocaml/tools/test-generator/.merlin +5 -0
  148. data/tracks/ocaml/tools/test-generator/Makefile +15 -0
  149. data/tracks/ocaml/tools/test-generator/_tags +0 -0
  150. data/tracks/ocaml/tools/test-generator/src/codegen.ml +17 -0
  151. data/tracks/ocaml/tools/test-generator/src/codegen.mli +7 -0
  152. data/tracks/ocaml/tools/test-generator/src/leap.json +39 -0
  153. data/tracks/ocaml/tools/test-generator/src/model.ml +31 -0
  154. data/tracks/ocaml/tools/test-generator/src/parser.ml +61 -0
  155. data/tracks/ocaml/tools/test-generator/src/parser.mli +9 -0
  156. data/tracks/ocaml/tools/test-generator/src/special_cases.ml +12 -0
  157. data/tracks/ocaml/tools/test-generator/src/special_cases.mli +7 -0
  158. data/tracks/ocaml/tools/test-generator/src/test_gen.ml +25 -0
  159. data/tracks/ocaml/tools/test-generator/src/test_generator.ml +62 -0
  160. data/tracks/ocaml/tools/test-generator/src/test_generator.mli +6 -0
  161. data/tracks/ocaml/tools/test-generator/src/utils.ml +32 -0
  162. data/tracks/ocaml/tools/test-generator/src/utils.mli +18 -0
  163. data/tracks/ocaml/tools/test-generator/templates/anagram/template.ml +17 -0
  164. data/tracks/ocaml/tools/test-generator/templates/bob/template.ml +15 -0
  165. data/tracks/ocaml/tools/test-generator/templates/hamming/template.ml +30 -0
  166. data/tracks/ocaml/tools/test-generator/templates/leap/template.ml +15 -0
  167. data/tracks/ocaml/tools/test-generator/templates/raindrops/template.ml +15 -0
  168. data/tracks/ocaml/tools/test-generator/templates/word-count/template.ml +19 -0
  169. data/tracks/ocaml/tools/test-generator/test/all_tests.ml +11 -0
  170. data/tracks/ocaml/tools/test-generator/test/codegen_test.ml +20 -0
  171. data/tracks/ocaml/tools/test-generator/test/model_test.ml +27 -0
  172. data/tracks/ocaml/tools/test-generator/test/parser_test.ml +73 -0
  173. data/tracks/ocaml/tools/test-generator/test/special_cases_test.ml +22 -0
  174. data/tracks/ocaml/tools/test-generator/test/test_generator_test.ml +11 -0
  175. data/tracks/ocaml/tools/test-generator/test/utils_test.ml +21 -0
  176. data/tracks/perl5/config.json +1 -1
  177. data/tracks/perl6/accumulate/accumulate.t +8 -2
  178. data/tracks/perl6/anagram/Example.pm +1 -1
  179. data/tracks/perl6/anagram/anagram.t +7 -8
  180. data/tracks/perl6/binary/Example.pm +1 -1
  181. data/tracks/perl6/binary/binary.t +7 -8
  182. data/tracks/perl6/bob/bob.t +1 -3
  183. data/tracks/perl6/config.json +1 -0
  184. data/tracks/perl6/grains/grains.t +7 -2
  185. data/tracks/perl6/leap/leap.t +3 -1
  186. data/tracks/perl6/raindrops/raindrops.t +8 -2
  187. data/tracks/perl6/rna-transcription/rna_transcription.t +8 -9
  188. data/tracks/perl6/robot-name/robot.t +8 -9
  189. data/tracks/perl6/scrabble-score/Example.pm +1 -1
  190. data/tracks/perl6/scrabble-score/scrabble_score.t +8 -2
  191. data/tracks/perl6/word-count/word_count.t +8 -2
  192. data/tracks/php/config.json +5 -0
  193. data/tracks/php/exercises/markdown/example.php +85 -0
  194. data/tracks/php/exercises/markdown/markdown.php +82 -0
  195. data/tracks/php/exercises/markdown/markdown_test.php +57 -0
  196. data/tracks/python/exercises/hamming/example.py +3 -0
  197. data/tracks/python/exercises/hamming/hamming_test.py +40 -14
  198. data/tracks/python/exercises/rna-transcription/example.py +6 -1
  199. data/tracks/python/exercises/rna-transcription/rna_transcription_test.py +9 -0
  200. data/tracks/ruby/config.json +6 -0
  201. data/tracks/ruby/exercises/dominoes/.version +1 -0
  202. data/tracks/ruby/exercises/dominoes/dominoes_test.rb +149 -0
  203. data/tracks/ruby/exercises/dominoes/example.rb +37 -0
  204. data/tracks/ruby/exercises/dominoes/example.tt +57 -0
  205. data/tracks/ruby/exercises/pangram/.version +1 -1
  206. data/tracks/ruby/exercises/pangram/example.rb +2 -2
  207. data/tracks/ruby/exercises/pangram/example.tt +5 -7
  208. data/tracks/ruby/exercises/pangram/pangram_test.rb +30 -25
  209. data/tracks/ruby/exercises/queen-attack/.version +1 -0
  210. data/tracks/ruby/exercises/queen-attack/example.rb +5 -30
  211. data/tracks/ruby/exercises/queen-attack/example.tt +22 -0
  212. data/tracks/ruby/exercises/queen-attack/queen_attack_test.rb +46 -95
  213. data/tracks/ruby/exercises/triangle/.version +1 -0
  214. data/tracks/ruby/exercises/triangle/example.rb +15 -22
  215. data/tracks/ruby/exercises/triangle/example.tt +20 -0
  216. data/tracks/ruby/exercises/triangle/triangle_test.rb +80 -40
  217. data/tracks/ruby/lib/dominoes_cases.rb +23 -0
  218. data/tracks/ruby/lib/pangram_cases.rb +19 -4
  219. data/tracks/ruby/lib/queen_attack_cases.rb +54 -0
  220. data/tracks/ruby/lib/triangle_cases.rb +51 -0
  221. data/tracks/scala/config.json +6 -0
  222. data/tracks/scala/exercises/dominoes/Example.scala +41 -0
  223. data/tracks/scala/exercises/dominoes/build.sbt +3 -0
  224. data/tracks/scala/exercises/dominoes/src/main/scala/Dominoes.scala +4 -0
  225. data/tracks/scala/exercises/dominoes/src/test/scala/DominoesSuite.scala +91 -0
  226. metadata +83 -2
@@ -2,159 +2,205 @@ var CustomSet = require('./custom-set');
2
2
 
3
3
  describe('CustomSet', function() {
4
4
 
5
- it('can test for no members', function() {
5
+ it('sets with no elements are empty', function() {
6
6
  var actual = new CustomSet().empty();
7
7
  expect(actual).toBe(true);
8
+ });
8
9
 
9
- var actual2 = new CustomSet([1]).empty();
10
- expect(actual2).toBe(false);
10
+ xit('sets with elements are not empty', function() {
11
+ var actual = new CustomSet([1]).empty();
12
+ expect(actual).toBe(false);
11
13
  });
12
14
 
13
- xit('can test for a member', function() {
15
+ xit('nothing is contained in an empty set', function() {
14
16
  var actual = new CustomSet().contains(1);
15
17
  expect(actual).toBe(false);
18
+ });
16
19
 
17
- var actual2 = new CustomSet([1, 2, 3]).contains(1);
18
- expect(actual2).toBe(true);
20
+ xit('when the element is in the set', function() {
21
+ var actual = new CustomSet([1, 2, 3]).contains(1);
22
+ expect(actual).toBe(true);
23
+ });
19
24
 
20
- var actual3 = new CustomSet([1, 2, 3]).contains(4);
21
- expect(actual3).toBe(false);
25
+ xit('when the element is not in the set', function() {
26
+ var actual = new CustomSet([1, 2, 3]).contains(4);
27
+ expect(actual).toBe(false);
22
28
  });
23
29
 
24
- xit('can test for subsets', function() {
30
+ xit('empty set is a subset of another empty set', function() {
25
31
  var actual = new CustomSet().subset(new CustomSet());
26
32
  expect(actual).toBe(true);
33
+ });
27
34
 
28
- var actual2 = new CustomSet([1]).subset(new CustomSet());
29
- expect(actual2).toBe(true);
35
+ xit('empty set is a subset of non-empty set', function() {
36
+ var actual = new CustomSet([1]).subset(new CustomSet());
37
+ expect(actual).toBe(true);
38
+ });
30
39
 
31
- var actual3 = new CustomSet().subset(new CustomSet([1]));
32
- expect(actual3).toBe(false);
40
+ xit('non-empty set is not a subset of empty set', function() {
41
+ var actual = new CustomSet().subset(new CustomSet([1]));
42
+ expect(actual).toBe(false);
43
+ });
33
44
 
34
- var actual4 = new CustomSet([1, 2, 3]).subset(new CustomSet([1, 2, 3]));
35
- expect(actual4).toBe(true);
45
+ xit('set is a subset of set with exact same elements', function() {
46
+ var actual = new CustomSet([1, 2, 3]).subset(new CustomSet([1, 2, 3]));
47
+ expect(actual).toBe(true);
48
+ });
36
49
 
37
- var actual5 = new CustomSet([4, 1, 2, 3]).subset(new CustomSet([1, 2, 3]));
38
- expect(actual5).toBe(true);
50
+ xit('set is a subset of larger set with same elements', function() {
51
+ var actual = new CustomSet([4, 1, 2, 3]).subset(new CustomSet([1, 2, 3]));
52
+ expect(actual).toBe(true);
53
+ });
39
54
 
40
- var actual6 = new CustomSet([4, 1, 3]).subset(new CustomSet([1, 2, 3]));
41
- expect(actual6).toBe(false);
55
+ xit('set is not a subset of set that does not contain its elements', function() {
56
+ var actual = new CustomSet([4, 1, 3]).subset(new CustomSet([1, 2, 3]));
57
+ expect(actual).toBe(false);
42
58
  });
43
59
 
44
- xit('can test disjoint', function() {
60
+ xit('the empty set is disjoint with itself', function() {
45
61
  var actual = new CustomSet().disjoint(new CustomSet());
46
62
  expect(actual).toBe(true);
63
+ });
47
64
 
48
- var actual2 = new CustomSet().disjoint(new CustomSet([1]));
49
- expect(actual2).toBe(true);
65
+ xit('empty set is disjoint with non-empty set', function() {
66
+ var actual = new CustomSet().disjoint(new CustomSet([1]));
67
+ expect(actual).toBe(true);
68
+ });
50
69
 
51
- var actual3 = new CustomSet([1]).disjoint(new CustomSet());
52
- expect(actual3).toBe(true);
70
+ xit('non-empty set is disjoint with empty set', function() {
71
+ var actual = new CustomSet([1]).disjoint(new CustomSet());
72
+ expect(actual).toBe(true);
73
+ });
53
74
 
54
- var actual4 = new CustomSet([1, 2]).disjoint(new CustomSet([2, 3]));
55
- expect(actual4).toBe(false);
75
+ xit('sets are not disjoint if they share an element', function() {
76
+ var actual = new CustomSet([1, 2]).disjoint(new CustomSet([2, 3]));
77
+ expect(actual).toBe(false);
78
+ });
56
79
 
57
- var actual5 = new CustomSet([1, 2]).disjoint(new CustomSet([3, 4]));
58
- expect(actual5).toBe(true);
80
+ xit('sets are disjoint if they share no elements', function() {
81
+ var actual = new CustomSet([1, 2]).disjoint(new CustomSet([3, 4]));
82
+ expect(actual).toBe(true);
59
83
  });
60
84
 
61
- xit('can test for equality', function () {
85
+ xit('empty sets are equal', function() {
62
86
  var actual = new CustomSet().eql(new CustomSet());
63
87
  expect(actual).toBe(true);
88
+ });
64
89
 
65
- var actual2 = new CustomSet().eql(new CustomSet([1, 2, 3]));
66
- expect(actual2).toBe(false);
90
+ xit('empty set is not equal to non-empty set', function() {
91
+ var actual = new CustomSet().eql(new CustomSet([1, 2, 3]));
92
+ expect(actual).toBe(false);
93
+ });
67
94
 
68
- var actual3 = new CustomSet([1, 2, 3]).eql(new CustomSet());
69
- expect(actual3).toBe(false);
95
+ xit('non-empty set is not equal to empty set', function() {
96
+ var actual = new CustomSet([1, 2, 3]).eql(new CustomSet());
97
+ expect(actual).toBe(false);
98
+ });
70
99
 
71
- var actual4 = new CustomSet([1, 2]).eql(new CustomSet([2, 1]));
72
- expect(actual4).toBe(true);
100
+ xit('sets with the same elements are equal', function() {
101
+ var actual = new CustomSet([1, 2]).eql(new CustomSet([2, 1]));
102
+ expect(actual).toBe(true);
103
+ });
73
104
 
74
- var actual5 = new CustomSet([1, 2, 3]).eql(new CustomSet([1, 2, 4]));
75
- expect(actual5).toBe(false);
105
+ xit('sets with different elements are not equal', function() {
106
+ var actual = new CustomSet([1, 2, 3]).eql(new CustomSet([1, 2, 4]));
107
+ expect(actual).toBe(false);
76
108
  });
77
109
 
78
- xit('can add a member', function() {
110
+ xit('add to empty set', function() {
79
111
  var actual = new CustomSet().add(3);
80
112
  var expected = new CustomSet([3]);
81
113
  expect(actual.eql(expected)).toBe(true);
114
+ });
82
115
 
83
- var actual2 = new CustomSet([1, 2, 4]).add(3);
84
- var expected2 = new CustomSet([1, 2, 3, 4]);
85
- expect(actual2.eql(expected2)).toBe(true);
116
+ xit('add to non-empty set', function() {
117
+ var actual = new CustomSet([1, 2, 4]).add(3);
118
+ var expected = new CustomSet([1, 2, 3, 4]);
119
+ expect(actual.eql(expected)).toBe(true);
120
+ });
86
121
 
87
- var actual3 = new CustomSet([1, 2, 3]).add(3);
88
- var expected3 = new CustomSet([1, 2, 3]);
89
- expect(actual3.eql(expected3)).toBe(true);
122
+ xit('adding an existing element does not change the set', function() {
123
+ var actual = new CustomSet([1, 2, 3]).add(3);
124
+ var expected = new CustomSet([1, 2, 3]);
125
+ expect(actual.eql(expected)).toBe(true);
90
126
  });
91
127
 
92
- xit('can check for intersection', function() {
128
+ xit('intersection of two empty sets is an empty set', function() {
93
129
  var actual = new CustomSet().intersection(new CustomSet());
94
130
  var expected = new CustomSet();
95
131
  expect(actual.eql(expected)).toBe(true);
132
+ });
96
133
 
97
- var actual2 = new CustomSet().intersection(new CustomSet([3, 2, 5]));
98
- var expected2 = new CustomSet();
99
- expect(actual2.eql(expected2)).toBe(true);
134
+ xit('intersection of an empty set and non-empty set is an empty set', function() {
135
+ var actual = new CustomSet().intersection(new CustomSet([3, 2, 5]));
136
+ var expected = new CustomSet();
137
+ expect(actual.eql(expected)).toBe(true);
138
+ });
100
139
 
101
- var actual3 = new CustomSet([1, 2, 3, 4]).intersection(new CustomSet());
102
- var expected3 = new CustomSet();
103
- expect(actual3.eql(expected3)).toBe(true);
140
+ xit('intersection of a non-empty set and an empty set is an empty set', function() {
141
+ var actual = new CustomSet([1, 2, 3, 4]).intersection(new CustomSet());
142
+ var expected = new CustomSet();
143
+ expect(actual.eql(expected)).toBe(true);
144
+ });
104
145
 
105
- var actual4 = new CustomSet([1, 2, 3]).intersection(new CustomSet([4, 5, 6]));
106
- var expected4 = new CustomSet();
107
- expect(actual4.eql(expected4)).toBe(true);
146
+ xit('intersection of two sets with no shared elements is an empty set', function() {
147
+ var actual = new CustomSet([1, 2, 3]).intersection(new CustomSet([4, 5, 6]));
148
+ var expected = new CustomSet();
149
+ expect(actual.eql(expected)).toBe(true);
150
+ });
108
151
 
109
- var actual5 = new CustomSet([1, 2, 3, 4]).intersection(new CustomSet([3, 2, 5]));
110
- var expected5 = new CustomSet([2, 3]);
111
- expect(actual5.eql(expected5)).toBe(true);
152
+ xit('intersection of two sets with shared elements is a set of the shared elements', function() {
153
+ var actual = new CustomSet([1, 2, 3, 4]).intersection(new CustomSet([3, 2, 5]));
154
+ var expected = new CustomSet([2, 3]);
155
+ expect(actual.eql(expected)).toBe(true);
112
156
  });
113
157
 
114
- xit('can check for difference', function(){
158
+ xit('difference of two empty sets is an empty set', function() {
115
159
  var actual = new CustomSet().difference(new CustomSet());
116
160
  var expected = new CustomSet();
117
161
  expect(actual.eql(expected)).toBe(true);
162
+ });
118
163
 
119
- var actual2 = new CustomSet().difference(new CustomSet([3, 2, 5]));
120
- var expected2 = new CustomSet();
121
- expect(actual2.eql(expected2)).toBe(true);
164
+ xit('difference of empty set and non-empty set is an empty set', function() {
165
+ var actual = new CustomSet().difference(new CustomSet([3, 2, 5]));
166
+ var expected = new CustomSet();
167
+ expect(actual.eql(expected)).toBe(true);
168
+ });
122
169
 
123
- var actual3 = new CustomSet([1, 2, 3, 4]).difference(new CustomSet());
124
- var expected3 = new CustomSet([1, 2, 3, 4]);
125
- expect(actual3.eql(expected3)).toBe(true);
170
+ xit('difference of a non-empty set and an empty set is the non-empty set', function() {
171
+ var actual = new CustomSet([1, 2, 3, 4]).difference(new CustomSet());
172
+ var expected = new CustomSet([1, 2, 3, 4]);
173
+ expect(actual.eql(expected)).toBe(true);
174
+ });
126
175
 
127
- var actual4 = new CustomSet([3, 2, 1]).difference(new CustomSet([2, 4]));
128
- var expected4 = new CustomSet([1, 3]);
129
- expect(actual4.eql(expected4)).toBe(true);
176
+ xit('difference of two non-empty sets is a set of elements that are only in the first set', function() {
177
+ var actual = new CustomSet([3, 2, 1]).difference(new CustomSet([2, 4]));
178
+ var expected = new CustomSet([1, 3]);
179
+ expect(actual.eql(expected)).toBe(true);
130
180
  });
131
181
 
132
- xit('can test for union', function() {
182
+ xit('union of empty sets is an empty set', function() {
133
183
  var actual = new CustomSet().union(new CustomSet());
134
184
  var expected = new CustomSet();
135
185
  expect(actual.eql(expected)).toBe(true);
186
+ });
136
187
 
137
- var actual2 = new CustomSet().union(new CustomSet([2]));
138
- var expected2 = new CustomSet([2]);
139
- expect(actual2.eql(expected2)).toBe(true);
140
-
141
- var actual3 = new CustomSet([1, 3]).union(new CustomSet());
142
- var expected3 = new CustomSet([1, 3]);
143
- expect(actual3.eql(expected3)).toBe(true);
144
-
145
- var actual4 = new CustomSet([1, 3]).union(new CustomSet([2, 3]));
146
- var expected4 = new CustomSet([3, 2, 1]);
147
- expect(actual4.eql(expected4)).toBe(true);
188
+ xit('union of an empty set and non-empty set is the non-empty set', function() {
189
+ var actual = new CustomSet().union(new CustomSet([2]));
190
+ var expected = new CustomSet([2]);
191
+ expect(actual.eql(expected)).toBe(true);
148
192
  });
149
193
 
150
- xit('can delete elements', function(){
194
+ xit('union of a non-empty set and empty set is the non-empty set', function() {
195
+ var actual = new CustomSet([1, 3]).union(new CustomSet());
151
196
  var expected = new CustomSet([1, 3]);
152
- var actual = new CustomSet([3, 2, 1]).delete(2);
153
197
  expect(actual.eql(expected)).toBe(true);
198
+ });
154
199
 
155
- var expected2 = new CustomSet([1, 2, 3]);
156
- var actual2 = new CustomSet([3, 2, 1]).delete(4);
157
- expect(actual2.eql(expected2)).toBe(true);
200
+ xit('union of non-empty sets contains all unique elements', function() {
201
+ var actual = new CustomSet([1, 3]).union(new CustomSet([2, 3]));
202
+ var expected = new CustomSet([3, 2, 1]);
203
+ expect(actual.eql(expected)).toBe(true);
158
204
  });
159
205
 
160
206
  xit('can be emptied', function() {
@@ -0,0 +1,200 @@
1
+ /**
2
+ * README
3
+ *
4
+ * Generates the custom-set exercise spec from the test metadata in x-common
5
+ *
6
+ * Prerequisites:
7
+ *
8
+ * - Node.js v6 or higher (for destructuring and template literals)
9
+ *
10
+ * - x-common and xjavascript checked out into the same parent directory
11
+ *
12
+ * - x-common up to date
13
+ *
14
+ * Run with:
15
+ *
16
+ * node example-gen.js
17
+ */
18
+
19
+ var fs = require('fs');
20
+ var path = require('path');
21
+
22
+ var EXERCISE_METADATA_ROOT = '../../../x-common/exercises';
23
+ var METADATA_FILE_NAME = 'canonical-data.json';
24
+ var METADATA_COMMENT_KEY = '#';
25
+ var EXERCISE_DIR_NAME = 'custom-set';
26
+ var SPEC_FILE_NAME = 'custom-set.spec.js';
27
+
28
+ var TEST_BODY_TEMPLATES = {
29
+ empty: function ({set, expected}) {
30
+ return (
31
+ `var actual = new CustomSet(${array(set)}).empty();
32
+ expect(actual).toBe(${expected});`);
33
+ },
34
+
35
+ contains: function ({set, element, expected}) {
36
+ return (
37
+ `var actual = new CustomSet(${array(set)}).contains(${element});
38
+ expect(actual).toBe(${expected});`);
39
+ },
40
+
41
+ subset: function ({set1, set2, expected}) {
42
+ return (
43
+ `var actual = new CustomSet(${array(set2)}).subset(new CustomSet(${array(set1)}));
44
+ expect(actual).toBe(${expected});`);
45
+ },
46
+
47
+ disjoint: function ({set1, set2, expected}) {
48
+ return (
49
+ `var actual = new CustomSet(${array(set1)}).disjoint(new CustomSet(${array(set2)}));
50
+ expect(actual).toBe(${expected});`);
51
+ },
52
+
53
+ equal: function ({set1, set2, expected}) {
54
+ return (
55
+ `var actual = new CustomSet(${array(set1)}).eql(new CustomSet(${array(set2)}));
56
+ expect(actual).toBe(${expected});`);
57
+ },
58
+
59
+ add: function ({set, element, expected}) {
60
+ return (
61
+ `var actual = new CustomSet(${array(set)}).add(${element});
62
+ var expected = new CustomSet(${array(expected)});
63
+ expect(actual.eql(expected)).toBe(true);`);
64
+ },
65
+
66
+ intersection: function ({set1, set2, expected}) {
67
+ return (
68
+ `var actual = new CustomSet(${array(set1)}).intersection(new CustomSet(${array(set2)}));
69
+ var expected = new CustomSet(${array(expected)});
70
+ expect(actual.eql(expected)).toBe(true);`);
71
+ },
72
+
73
+ difference: function ({set1, set2, expected}) {
74
+ return (
75
+ `var actual = new CustomSet(${array(set1)}).difference(new CustomSet(${array(set2)}));
76
+ var expected = new CustomSet(${array(expected)});
77
+ expect(actual.eql(expected)).toBe(true);`);
78
+ },
79
+
80
+ union: function ({set1, set2, expected}) {
81
+ return (
82
+ `var actual = new CustomSet(${array(set1)}).union(new CustomSet(${array(set2)}));
83
+ var expected = new CustomSet(${array(expected)});
84
+ expect(actual.eql(expected)).toBe(true);`);
85
+ }
86
+ }
87
+
88
+ var NON_CANONICAL_TESTS = `
89
+ xit('can be emptied', function() {
90
+ var actual = new CustomSet([1, 2]).clear();
91
+ var expected = new CustomSet();
92
+ expect(actual.eql(expected)).toBe(true);
93
+ var actual2 = new CustomSet().clear();
94
+ var expected2 = new CustomSet();
95
+ expect(actual2.eql(expected2)).toBe(true);
96
+ });
97
+
98
+ xit('knows its size', function() {
99
+ var actual = new CustomSet().size();
100
+ expect(actual).toBe(0);
101
+ var actual2 = new CustomSet([1, 2, 3]).size();
102
+ expect(actual2).toBe(3);
103
+ var actual3 = new CustomSet([1, 2, 3, 2]).size();
104
+ expect(actual3).toBe(3);
105
+ });
106
+
107
+ xit('can give back a list', function() {
108
+ var actual = new CustomSet().toList();
109
+ var expected = [];
110
+ expect(actual.sort()).toEqual(expected);
111
+ var actual2 = new CustomSet([3, 1, 2]).toList();
112
+ var expected2 = [1, 2, 3];
113
+ expect(actual2.sort()).toEqual(expected2);
114
+ var actual3 = new CustomSet([3, 1, 2, 1]).toList();
115
+ var expected3 = [1, 2, 3];
116
+ expect(actual3.sort()).toEqual(expected3);
117
+ });
118
+ `
119
+
120
+ function render ({suiteData, testBodyTemplates, extraTests, suiteTemplate}) {
121
+ var testCases = extractTestCases(suiteData, testBodyTemplates);
122
+ var tests = renderTests(testCases);
123
+
124
+ return renderSuite(tests, extraTests, suiteTemplate);
125
+ }
126
+
127
+ function extractTestCases (suiteData, testBodyTemplates) {
128
+ var testCases = [];
129
+
130
+ Object.keys(suiteData)
131
+ .filter(function (key) {
132
+ return key !== METADATA_COMMENT_KEY;
133
+ })
134
+ .forEach(function (sectionName) {
135
+ suiteData[sectionName]['cases']
136
+ .forEach(function (caseData) {
137
+ testCases.push(new TestCase(caseData, testBodyTemplates[sectionName]));
138
+ })
139
+ })
140
+
141
+ return testCases;
142
+ }
143
+
144
+ function TestCase (caseData, bodyTemplate) {
145
+ this.caseData = caseData;
146
+ this.bodyTemplate = bodyTemplate;
147
+ }
148
+
149
+ TestCase.prototype.render = function (isEnabled) {
150
+ return testTemplate(isEnabled, this.caseData.description, this.bodyTemplate(this.caseData));
151
+ }
152
+
153
+ function renderTests (testCases) {
154
+ return testCases.reduce(function (output, testCase, index) {
155
+ return output + testCase.render(index === 0);
156
+ }, '')
157
+ }
158
+
159
+ function renderSuite (tests, otherTests, suiteTemplate) {
160
+ return suiteTemplate(tests.concat(otherTests));
161
+ }
162
+
163
+ function suiteTemplate (tests) {
164
+ return (
165
+ `var CustomSet = require('./custom-set');
166
+
167
+ describe('CustomSet', function() {
168
+ ${tests}
169
+ });
170
+ `);
171
+ }
172
+
173
+ function testTemplate (isEnabled, description, body) {
174
+ return (
175
+ `
176
+ ${isEnabled ? 'it' : 'xit'}('${description}', function() {
177
+ ${body}
178
+ });
179
+ `);
180
+ }
181
+
182
+ function array (array) {
183
+ return array.length === 0 ? '' : `[${array.join(', ')}]`;
184
+ }
185
+
186
+ function generate () {
187
+ var exerciseFilePath = path.join(EXERCISE_METADATA_ROOT, EXERCISE_DIR_NAME, METADATA_FILE_NAME);
188
+ var suiteData = JSON.parse(fs.readFileSync(exerciseFilePath));
189
+
190
+ return fs.writeFileSync(
191
+ SPEC_FILE_NAME,
192
+ render({
193
+ suiteData: suiteData,
194
+ testBodyTemplates: TEST_BODY_TEMPLATES,
195
+ extraTests: NON_CANONICAL_TESTS,
196
+ suiteTemplate: suiteTemplate
197
+ }));
198
+ }
199
+
200
+ generate();
@@ -2,7 +2,7 @@
2
2
  ASSIGNMENT ?= ""
3
3
  ASSIGNMENTS = $(shell find ./exercises -maxdepth 1 -mindepth 1 -type d | awk -F/ '{print $$NF}' | sort)
4
4
 
5
- default: test
5
+ default: testgenerator test
6
6
 
7
7
  # output directories
8
8
  TMPDIR ?= "/tmp/"
@@ -27,6 +27,9 @@ test-assignment:
27
27
  @make -C $(OUTDIR)
28
28
  @rm -rf $(OUTDIR)
29
29
 
30
+ testgenerator:
31
+ make -C ./tools/test-generator
32
+
30
33
  # all tests
31
34
  test:
32
35
  @for assignment in $(ASSIGNMENTS); do \
@@ -34,6 +37,7 @@ test:
34
37
  done
35
38
 
36
39
  clean:
40
+ make -C ./tools/test-generator clean
37
41
  @for assignment in $(ASSIGNMENTS); do \
38
42
  make -C ./exercises/$$assignment clean;\
39
43
  done
@@ -150,7 +150,8 @@
150
150
  ],
151
151
  "ignored": [
152
152
  "docs",
153
- "img"
153
+ "img",
154
+ "tools"
154
155
  ],
155
156
  "foregone": [
156
157
 
@@ -6,29 +6,40 @@ let ae exp got _test_ctxt =
6
6
  let printer = List.to_string ~f:String.to_string in
7
7
  assert_equal exp got ~cmp:(List.equal ~equal:String.equal) ~printer
8
8
 
9
- let tests =
10
- ["no matches">::
11
- ae [] (anagrams "diaper" ["hello"; "world"; "zombies"; "pants"]);
12
- "detect simple anagrams">::
13
- ae ["tan"] (anagrams "ant" ["tan"; "stand"; "at"]);
14
- "detect multiple anagrams">::
15
- ae ["stream"; "maters"] (anagrams "master" ["stream"; "pigeon"; "maters"]);
16
- "do not detect anagram subsets">::
17
- ae [] (anagrams "good" ["dog"; "goody"]);
18
- "multiple anagrams">::
19
- ae ["gallery"; "regally"; "largely"]
20
- (anagrams "allergy" ["gallery"; "ballerina"; "regally"; "clergy";
21
- "largely"; "leading"]);
22
- "detect anagrams case-insensitively">::
23
- ae ["Carthorse"]
24
- (anagrams "Orchestra" ["cashregister"; "Carthorse"; "radishes"]);
25
- "anagrams must not be the source word">::
26
- ae [] (anagrams "banana" ["banana"]);
27
- "anagrams must not be the source word case-insensitively">::
28
- ae [] (anagrams "banana" ["Banana"]);
29
- "anagrams must use all letters exactly once">::
30
- ae [] (anagrams "patter" ["tapper"]);
31
- ]
9
+ let tests = [
10
+ "no matches" >::
11
+ ae [] (anagrams "diaper" ["hello"; "world"; "zombies"; "pants"]);
12
+ "detects simple anagram" >::
13
+ ae ["tan"] (anagrams "ant" ["tan"; "stand"; "at"]);
14
+ "does not detect false positives" >::
15
+ ae [] (anagrams "galea" ["eagle"]);
16
+ "detects multiple anagrams" >::
17
+ ae ["stream"; "maters"] (anagrams "master" ["stream"; "pigeon"; "maters"]);
18
+ "does not detect anagram subsets" >::
19
+ ae [] (anagrams "good" ["dog"; "goody"]);
20
+ "detects anagram" >::
21
+ ae ["inlets"] (anagrams "listen" ["enlists"; "google"; "inlets"; "banana"]);
22
+ "detects multiple anagrams" >::
23
+ ae ["gallery"; "regally"; "largely"] (anagrams "allergy" ["gallery"; "ballerina"; "regally"; "clergy"; "largely"; "leading"]);
24
+ "does not detect identical words" >::
25
+ ae ["cron"] (anagrams "corn" ["corn"; "dark"; "Corn"; "rank"; "CORN"; "cron"; "park"]);
26
+ "does not detect non-anagrams with identical checksum" >::
27
+ ae [] (anagrams "mass" ["last"]);
28
+ "detects anagrams case-insensitively" >::
29
+ ae ["Carthorse"] (anagrams "Orchestra" ["cashregister"; "Carthorse"; "radishes"]);
30
+ "detects anagrams using case-insensitive subject" >::
31
+ ae ["carthorse"] (anagrams "Orchestra" ["cashregister"; "carthorse"; "radishes"]);
32
+ "detects anagrams using case-insensitive possible matches" >::
33
+ ae ["Carthorse"] (anagrams "orchestra" ["cashregister"; "Carthorse"; "radishes"]);
34
+ "does not detect a word as its own anagram" >::
35
+ ae [] (anagrams "banana" ["Banana"]);
36
+ "does not detect a anagram if the original word is repeated" >::
37
+ ae [] (anagrams "go" ["go Go GO"]);
38
+ "anagrams must use all letters exactly once" >::
39
+ ae [] (anagrams "tapper" ["patter"]);
40
+ "capital word is not own anagram" >::
41
+ ae [] (anagrams "BANANA" ["Banana"]);
42
+ ]
32
43
 
33
44
  let () =
34
- run_test_tt_main ("anagrams tests" >::: tests)
45
+ run_test_tt_main ("anagrams tests" >::: tests)
@@ -6,7 +6,7 @@ let is_shouting s =
6
6
  String.exists ~f:Char.is_alpha s &&
7
7
  String.for_all ~f:(fun c -> not (Char.is_alpha c) || Char.is_uppercase c) s
8
8
 
9
- let is_question = String.is_suffix ~suffix:"?"
9
+ let is_question s = String.is_suffix ~suffix:"?" (String.strip s)
10
10
 
11
11
  let response_for = function
12
12
  | s when is_empty s -> "Fine. Be that way!"