trackler 2.0.0.1 → 2.0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (226) hide show
  1. checksums.yaml +4 -4
  2. data/bin/bump-content +3 -1
  3. data/bin/verify-metadata +2 -2
  4. data/common/exercises/alphametics/canonical-data.json +19 -9
  5. data/common/exercises/food-chain/canonical-data.json +7 -1
  6. data/common/exercises/grains/canonical-data.json +66 -0
  7. data/common/exercises/raindrops/description.md +4 -5
  8. data/common/exercises/triangle/canonical-data.json +81 -54
  9. data/lib/trackler/version.rb +1 -1
  10. data/tracks/c/config.json +26 -19
  11. data/tracks/c/exercises/allergies/makefile +15 -0
  12. data/tracks/c/exercises/allergies/src/allergies.h +21 -0
  13. data/tracks/c/exercises/allergies/src/example.c +32 -0
  14. data/tracks/c/exercises/allergies/src/example.h +26 -0
  15. data/tracks/c/exercises/allergies/test/test_allergies.c +203 -0
  16. data/tracks/c/exercises/allergies/test/vendor/unity.c +1300 -0
  17. data/tracks/c/exercises/allergies/test/vendor/unity.h +274 -0
  18. data/tracks/c/exercises/allergies/test/vendor/unity_internals.h +701 -0
  19. data/tracks/c/exercises/atbash-cipher/makefile +16 -0
  20. data/tracks/c/exercises/atbash-cipher/src/example.c +71 -0
  21. data/tracks/c/exercises/atbash-cipher/src/example.h +7 -0
  22. data/tracks/c/exercises/atbash-cipher/test/test_atbash_cipher.c +113 -0
  23. data/tracks/c/exercises/atbash-cipher/test/vendor/unity.c +1300 -0
  24. data/tracks/c/exercises/atbash-cipher/test/vendor/unity.h +274 -0
  25. data/tracks/c/exercises/atbash-cipher/test/vendor/unity_internals.h +701 -0
  26. data/tracks/c/exercises/phone-number/makefile +16 -0
  27. data/tracks/c/exercises/phone-number/src/example.c +66 -0
  28. data/tracks/c/exercises/phone-number/src/example.h +8 -0
  29. data/tracks/c/exercises/phone-number/test/test_phone_number.c +108 -0
  30. data/tracks/c/exercises/phone-number/test/vendor/unity.c +1300 -0
  31. data/tracks/c/exercises/phone-number/test/vendor/unity.h +274 -0
  32. data/tracks/c/exercises/phone-number/test/vendor/unity_internals.h +701 -0
  33. data/tracks/csharp/config.json +8 -0
  34. data/tracks/csharp/exercises/bowling/BowlingTest.cs +188 -33
  35. data/tracks/csharp/exercises/bowling/Example.cs +38 -9
  36. data/tracks/csharp/exercises/rectangles/Example.cs +91 -0
  37. data/tracks/csharp/exercises/rectangles/RectanglesTest.cs +133 -0
  38. data/tracks/elisp/docs/INSTALLATION.org +1 -1
  39. data/tracks/elixir/config.json +8 -66
  40. data/tracks/elixir/docs/LEARNING.md +1 -1
  41. data/tracks/elixir/exercises/diamond/diamond_test.exs +12 -12
  42. data/tracks/elixir/exercises/grep/example.exs +92 -0
  43. data/tracks/elixir/exercises/grep/grep.exs +6 -0
  44. data/tracks/elixir/exercises/grep/grep_test.exs +259 -0
  45. data/tracks/elixir/exercises/markdown/markdown.exs +59 -2
  46. data/tracks/elixir/exercises/nucleotide-count/nucleotide_count_test.exs +4 -4
  47. data/tracks/elixir/exercises/phone-number/phone_number_test.exs +5 -0
  48. data/tracks/fsharp/exercises/bowling/BowlingTest.fs +158 -43
  49. data/tracks/fsharp/exercises/bowling/Example.fs +53 -24
  50. data/tracks/go/config.json +5 -0
  51. data/tracks/go/exercises/diamond/diamond_test.go +227 -0
  52. data/tracks/go/exercises/diamond/example.go +47 -0
  53. data/tracks/go/exercises/food-chain/example.go +1 -1
  54. data/tracks/go/exercises/food-chain/food_chain_test.go +30 -6
  55. data/tracks/go/exercises/nucleotide-count/example.go +21 -8
  56. data/tracks/go/exercises/nucleotide-count/nucleotide_count_test.go +45 -37
  57. data/tracks/haskell/exercises/anagram/test/Tests.hs +1 -11
  58. data/tracks/java/bin/journey-test.sh +165 -128
  59. data/tracks/java/docs/ABOUT.md +5 -8
  60. data/tracks/java/exercises/hello-world/build.gradle +0 -6
  61. data/tracks/java/exercises/hello-world/src/test/java/HelloWorldTest.java +0 -1
  62. data/tracks/java/exercises/meetup/build.gradle +0 -1
  63. data/tracks/java/exercises/meetup/src/example/java/Meetup.java +9 -7
  64. data/tracks/java/exercises/meetup/src/test/java/MeetupTest.java +185 -188
  65. data/tracks/lua/config.json +0 -73
  66. data/tracks/lua/exercises/bowling/bowling_spec.lua +92 -48
  67. data/tracks/lua/exercises/bowling/example.lua +4 -1
  68. data/tracks/objective-c/config.json +9 -30
  69. data/tracks/objective-c/exercises/pangram/PangramExample.h +7 -0
  70. data/tracks/objective-c/exercises/pangram/PangramExample.m +21 -0
  71. data/tracks/objective-c/exercises/pangram/PangramTest.m +51 -0
  72. data/tracks/objective-c/xcodeProject/ObjectiveC.xcodeproj/project.pbxproj +18 -0
  73. data/tracks/ocaml/README.md +46 -1
  74. data/tracks/ocaml/SETUP.md +21 -2
  75. data/tracks/ocaml/config.json +48 -78
  76. data/tracks/perl5/README.md +15 -8
  77. data/tracks/perl5/testall.pl +5 -5
  78. data/tracks/php/config.json +26 -34
  79. data/tracks/php/docs/ABOUT.md +15 -0
  80. data/tracks/php/exercises/allergies/allergies_test.php +121 -0
  81. data/tracks/php/exercises/allergies/example.php +64 -0
  82. data/tracks/php/exercises/etl/etl_test.php +52 -0
  83. data/tracks/php/exercises/etl/example.php +12 -0
  84. data/tracks/php/exercises/nucleotide-count/example.php +25 -0
  85. data/tracks/php/exercises/nucleotide-count/nucleotide-count_test.php +36 -0
  86. data/tracks/php/exercises/pig-latin/example.php +25 -29
  87. data/tracks/php/exercises/pig-latin/pig-latin_test.php +26 -19
  88. data/tracks/php/exercises/space-age/example.php +65 -0
  89. data/tracks/php/exercises/space-age/space-age_test.php +70 -0
  90. data/tracks/php/exercises/triangle/example.php +43 -0
  91. data/tracks/php/exercises/triangle/triangle_test.php +140 -0
  92. data/tracks/pony/exercises/anagram/example.pony +6 -6
  93. data/tracks/pony/exercises/anagram/test.pony +3 -4
  94. data/tracks/pony/exercises/bob/test.pony +23 -23
  95. data/tracks/pony/exercises/difference-of-squares/test.pony +11 -11
  96. data/tracks/pony/exercises/hamming/example.pony +3 -3
  97. data/tracks/pony/exercises/hamming/test.pony +16 -16
  98. data/tracks/pony/exercises/hello-world/test.pony +5 -4
  99. data/tracks/pony/exercises/leap/test.pony +8 -8
  100. data/tracks/python/config.json +18 -0
  101. data/tracks/python/exercises/diamond/diamond_test.py +33 -0
  102. data/tracks/python/exercises/diamond/example.py +15 -0
  103. data/tracks/python/exercises/linked-list/example.py +47 -0
  104. data/tracks/python/exercises/linked-list/linked_list.py +13 -0
  105. data/tracks/python/exercises/linked-list/linked_list_test.py +49 -0
  106. data/tracks/python/exercises/list-ops/example.py +55 -0
  107. data/tracks/python/exercises/list-ops/list_ops.py +38 -0
  108. data/tracks/python/exercises/list-ops/list_ops_test.py +136 -0
  109. data/tracks/ruby/bin/generate +22 -2
  110. data/tracks/ruby/config.json +12 -83
  111. data/tracks/ruby/exercises/allergies/allergies_test.rb +0 -1
  112. data/tracks/ruby/exercises/atbash-cipher/atbash_cipher_test.rb +0 -1
  113. data/tracks/ruby/exercises/beer-song/beer_song_test.rb +1 -2
  114. data/tracks/ruby/exercises/binary/example.rb +0 -1
  115. data/tracks/ruby/exercises/binary-search-tree/binary_search_tree_test.rb +1 -1
  116. data/tracks/ruby/exercises/bowling/.version +1 -0
  117. data/tracks/ruby/exercises/bowling/bowling_test.rb +109 -133
  118. data/tracks/ruby/exercises/bowling/example.rb +7 -7
  119. data/tracks/ruby/exercises/bowling/example.tt +27 -0
  120. data/tracks/ruby/exercises/circular-buffer/circular_buffer_test.rb +0 -2
  121. data/tracks/ruby/exercises/clock/example.rb +0 -2
  122. data/tracks/ruby/exercises/connect/connect_test.rb +0 -1
  123. data/tracks/ruby/exercises/custom-set/custom_set_test.rb +0 -1
  124. data/tracks/ruby/exercises/diamond/diamond_test.rb +0 -1
  125. data/tracks/ruby/exercises/etl/etl_test.rb +1 -1
  126. data/tracks/ruby/exercises/house/house_test.rb +0 -1
  127. data/tracks/ruby/exercises/isogram/isogram_test.rb +2 -2
  128. data/tracks/ruby/exercises/largest-series-product/example.tt +0 -3
  129. data/tracks/ruby/exercises/largest-series-product/largest_series_product_test.rb +0 -4
  130. data/tracks/ruby/exercises/linked-list/linked_list_test.rb +1 -1
  131. data/tracks/ruby/exercises/meetup/meetup_test.rb +0 -1
  132. data/tracks/ruby/exercises/nth-prime/example.tt +0 -2
  133. data/tracks/ruby/exercises/nth-prime/nth_prime_test.rb +0 -2
  134. data/tracks/ruby/exercises/ocr-numbers/ocr_numbers_test.rb +1 -2
  135. data/tracks/ruby/exercises/protein-translation/protein_translation_test.rb +0 -1
  136. data/tracks/ruby/exercises/proverb/proverb_test.rb +1 -3
  137. data/tracks/ruby/exercises/queen-attack/example.rb +3 -1
  138. data/tracks/ruby/exercises/queen-attack/queen_attack_test.rb +34 -8
  139. data/tracks/ruby/exercises/robot-simulator/robot_simulator_test.rb +1 -1
  140. data/tracks/ruby/exercises/strain/strain_test.rb +2 -2
  141. data/tracks/ruby/exercises/tournament/.version +1 -0
  142. data/tracks/ruby/exercises/tournament/example.rb +54 -0
  143. data/tracks/ruby/exercises/tournament/example.tt +23 -0
  144. data/tracks/ruby/exercises/tournament/tournament_test.rb +92 -0
  145. data/tracks/ruby/exercises/transpose/.version +1 -0
  146. data/tracks/ruby/exercises/transpose/example.rb +14 -0
  147. data/tracks/ruby/exercises/transpose/example.tt +22 -0
  148. data/tracks/ruby/exercises/transpose/transpose_test.rb +303 -0
  149. data/tracks/ruby/lib/bowling_cases.rb +46 -0
  150. data/tracks/ruby/lib/isogram_cases.rb +1 -1
  151. data/tracks/ruby/lib/tournament_cases.rb +45 -0
  152. data/tracks/ruby/lib/transpose_cases.rb +45 -0
  153. data/tracks/rust/config.json +2 -0
  154. data/tracks/rust/exercises/bowling/.gitignore +7 -0
  155. data/tracks/rust/exercises/bowling/Cargo.toml +3 -0
  156. data/tracks/rust/exercises/bowling/example.rs +134 -0
  157. data/tracks/rust/exercises/bowling/tests/bowling.rs +373 -0
  158. data/tracks/rust/exercises/grains/.gitignore +7 -0
  159. data/tracks/rust/exercises/grains/Cargo.toml +3 -0
  160. data/tracks/rust/exercises/grains/example.rs +11 -0
  161. data/tracks/rust/exercises/grains/src/lib.rs +7 -0
  162. data/tracks/rust/exercises/grains/tests/grains.rs +63 -0
  163. data/tracks/rust/problems.md +2 -0
  164. data/tracks/scala/README.md +38 -0
  165. data/tracks/scala/config.json +20 -74
  166. data/tracks/scala/exercises/accumulate/src/test/scala/accumulate_test.scala +4 -0
  167. data/tracks/scala/exercises/allergies/src/test/scala/allergies_test.scala +11 -0
  168. data/tracks/scala/exercises/alphametics/build.sbt +6 -0
  169. data/tracks/scala/exercises/alphametics/example.scala +125 -0
  170. data/tracks/scala/exercises/alphametics/src/main/scala/.keep +0 -0
  171. data/tracks/scala/exercises/alphametics/src/test/scala/AlphameticsTest.scala +62 -0
  172. data/tracks/scala/exercises/atbash-cipher/src/test/scala/atbash_test.scala +8 -0
  173. data/tracks/scala/exercises/bank-account/src/test/scala/BankAccountTest.scala +4 -0
  174. data/tracks/scala/exercises/binary/src/test/scala/binary_test.scala +13 -0
  175. data/tracks/scala/exercises/binary-search-tree/src/test/scala/BstTest.scala +11 -0
  176. data/tracks/scala/exercises/bowling/Example.scala +116 -0
  177. data/tracks/scala/exercises/bowling/build.sbt +3 -0
  178. data/tracks/scala/exercises/bowling/src/main/scala/Bowling.scala +11 -0
  179. data/tracks/scala/exercises/bowling/src/test/scala/BowlingSuite.scala +237 -0
  180. data/tracks/scala/exercises/clock/src/test/scala/ClockTest.scala +50 -0
  181. data/tracks/scala/exercises/connect/README.md +17 -0
  182. data/tracks/scala/exercises/connect/src/test/scala/ConnectTest.scala +7 -0
  183. data/tracks/scala/exercises/crypto-square/src/test/scala/{CrytpoSquareTest.scala → CryptoSquareTest.scala} +9 -0
  184. data/tracks/scala/exercises/custom-set/src/test/scala/CustomSetTest.scala +36 -0
  185. data/tracks/scala/exercises/difference-of-squares/src/test/scala/squares_test.scala +8 -0
  186. data/tracks/scala/exercises/forth/src/test/scala/ForthTest.scala +22 -0
  187. data/tracks/scala/exercises/hexadecimal/src/test/scala/HexadecimalTest.scala +8 -0
  188. data/tracks/scala/exercises/kindergarten-garden/src/test/scala/GardenTest.scala +5 -0
  189. data/tracks/scala/exercises/largest-series-product/src/test/scala/SeriesTest.scala +2 -0
  190. data/tracks/scala/exercises/linked-list/src/test/scala/DequeTest.scala +4 -0
  191. data/tracks/scala/exercises/luhn/src/test/scala/LuhnTest.scala +4 -0
  192. data/tracks/scala/exercises/matrix/src/test/scala/MatrixTest.scala +2 -0
  193. data/tracks/scala/exercises/minesweeper/src/test/scala/MinesweeperTest.scala +6 -0
  194. data/tracks/scala/exercises/nth-prime/src/test/scala/PrimeTest.scala +5 -0
  195. data/tracks/scala/exercises/ocr-numbers/src/test/scala/OcrTest.scala +15 -0
  196. data/tracks/scala/exercises/octal/src/test/scala/OctalTest.scala +7 -0
  197. data/tracks/scala/exercises/parallel-letter-frequency/src/test/scala/FrequencyTest.scala +8 -0
  198. data/tracks/scala/exercises/pascals-triangle/src/test/scala/PascalsTriangleTest.scala +5 -0
  199. data/tracks/scala/exercises/pig-latin/src/test/scala/PigLatinTest.scala +4 -0
  200. data/tracks/scala/exercises/pythagorean-triplet/src/test/scala/PythagoreanTripletTest.scala +3 -0
  201. data/tracks/scala/exercises/queen-attack/src/test/scala/QueensTest.scala +5 -0
  202. data/tracks/scala/exercises/robot-simulator/src/test/scala/RobotTest.scala +16 -8
  203. data/tracks/scala/exercises/say/src/test/scala/SayTest.scala +34 -17
  204. data/tracks/scala/exercises/scrabble-score/src/test/scala/scrabble_score_test.scala +6 -0
  205. data/tracks/scala/exercises/secret-handshake/src/test/scala/SecretHandshakeTest.scala +18 -9
  206. data/tracks/scala/exercises/series/src/test/scala/SeriesTest.scala +4 -2
  207. data/tracks/scala/exercises/sieve/src/test/scala/SieveTest.scala +8 -4
  208. data/tracks/scala/exercises/simple-cipher/src/test/scala/CipherTest.scala +17 -9
  209. data/tracks/scala/exercises/sublist/src/test/scala/sublist_test.scala +17 -0
  210. data/tracks/scala/exercises/trinary/src/test/scala/TrinaryTest.scala +14 -7
  211. data/tracks/scala/exercises/wordy/src/test/scala/WordProblemTest.scala +28 -14
  212. data/tracks/scala/project/Build.scala +3 -3
  213. data/tracks/scala/testgen/src/main/scala/BowlingTestGenerator.scala +57 -0
  214. data/tracks/sml/config.json +41 -6
  215. data/tracks/sml/exercises/flatten-array/example.sml +6 -0
  216. data/tracks/sml/exercises/flatten-array/test_flatten_array.sml +10 -0
  217. data/tracks/sml/exercises/nth-prime/example.sml +46 -0
  218. data/tracks/sml/exercises/nth-prime/test_nth_prime.sml +14 -0
  219. data/tracks/sml/exercises/raindrops/example.sml +9 -0
  220. data/tracks/sml/exercises/raindrops/raindrops.sml +2 -0
  221. data/tracks/sml/exercises/raindrops/test_raindrops.sml +95 -0
  222. data/tracks/swift/config.json +269 -328
  223. data/tracks/swift/exercises/pangram/PangramExample.swift +17 -0
  224. data/tracks/swift/exercises/pangram/PangramTest.swift +43 -0
  225. data/tracks/swift/xcodeProject/xSwift.xcodeproj/project.pbxproj +16 -0
  226. metadata +95 -3
@@ -4,79 +4,6 @@
4
4
  "repository": "https://github.com/exercism/xlua",
5
5
  "active": true,
6
6
  "test_pattern": ".*spec[.]lua$",
7
- "problems": [
8
- "hello-world",
9
- "accumulate",
10
- "hamming",
11
- "house",
12
- "raindrops",
13
- "bob",
14
- "difference-of-squares",
15
- "anagram",
16
- "octal",
17
- "binary-search",
18
- "bracket-push",
19
- "flatten-array",
20
- "word-count",
21
- "pangram",
22
- "matrix",
23
- "beer-song",
24
- "isogram",
25
- "perfect-numbers",
26
- "etl",
27
- "nucleotide-count",
28
- "food-chain",
29
- "sum-of-multiples",
30
- "rna-transcription",
31
- "phone-number",
32
- "bank-account",
33
- "protein-translation",
34
- "grade-school",
35
- "nth-prime",
36
- "diamond",
37
- "run-length-encoding",
38
- "sublist",
39
- "robot-name",
40
- "robot-simulator",
41
- "pythagorean-triplet",
42
- "leap",
43
- "space-age",
44
- "pascals-triangle",
45
- "sieve",
46
- "grains",
47
- "kindergarten-garden",
48
- "custom-set",
49
- "gigasecond",
50
- "word-search",
51
- "luhn",
52
- "triangle",
53
- "clock",
54
- "series",
55
- "linked-list",
56
- "ocr-numbers",
57
- "pig-latin",
58
- "minesweeper",
59
- "crypto-square",
60
- "list-ops",
61
- "atbash-cipher",
62
- "scrabble-score",
63
- "largest-series-product",
64
- "rail-fence-cipher",
65
- "roman-numerals",
66
- "transpose",
67
- "circular-buffer",
68
- "binary-search-tree",
69
- "bowling",
70
- "binary",
71
- "alphametics",
72
- "prime-factors",
73
- "acronym",
74
- "all-your-base",
75
- "rectangles",
76
- "allergies",
77
- "pov",
78
- "change"
79
- ],
80
7
  "exercises": [{
81
8
  "slug": "hello-world",
82
9
  "difficulty": 1,
@@ -17,44 +17,56 @@ describe('bowling', function()
17
17
  end
18
18
  end
19
19
 
20
- it('should not allow the score to be taken at the beginning of the game', function()
21
- assert.has_error(function() scorer.score() end)
22
- end)
23
-
24
- it('should not allow the score to be taken before 10 frames have been played', function()
25
- roll_n_times(0, 19)
26
- assert.has_error(function() scorer.score() end)
20
+ it('should score a game with all gutterballs', function()
21
+ roll_n_times(0, 20)
22
+ assert.equal(0, scorer.score())
27
23
  end)
28
24
 
29
- it('should not allow more rolls after 10 frames have been played', function()
30
- roll_n_times(0, 20)
31
- assert.has_error(function() scorer.roll(0) end)
25
+ it('should allow a game with all open frames', function()
26
+ roll_n_times({ 6, 3 }, 10)
27
+ assert.equal(90, scorer.score())
32
28
  end)
33
29
 
34
- it('should not allow a roll with negative pins', function()
35
- assert.has_error(function() scorer.roll(-1) end)
30
+ it('should score a spare followed by zeros as 10', function()
31
+ scorer.roll(6)
32
+ scorer.roll(4)
33
+ roll_n_times(0, 18)
34
+ assert.equal(10, scorer.score())
36
35
  end)
37
36
 
38
- it('should not allow a roll better than a strike', function()
39
- assert.has_error(function() scorer.roll(11) end)
37
+ it('should count points scored in the roll after a spare twice', function()
38
+ scorer.roll(6)
39
+ scorer.roll(4)
40
+ scorer.roll(3)
41
+ roll_n_times(0, 17)
42
+ assert.equal(16, scorer.score())
40
43
  end)
41
44
 
42
- it('should score a game with all gutterballs', function()
43
- roll_n_times(0, 20)
44
- assert.equal(0, scorer.score())
45
+ it('should allow a one roll bonus for each consecutive spare', function()
46
+ scorer.roll(5)
47
+ scorer.roll(5)
48
+ scorer.roll(3)
49
+ scorer.roll(7)
50
+ scorer.roll(4)
51
+ roll_n_times(0, 15)
52
+ assert.equal(31, scorer.score())
45
53
  end)
46
54
 
47
- it('should score a game with all single pin rolls', function()
48
- roll_n_times(1, 20)
49
- assert.equal(20, scorer.score())
55
+ it('should score a fill ball for a spare in the last frame', function()
56
+ roll_n_times(0, 18)
57
+ scorer.roll(7)
58
+ scorer.roll(3)
59
+ scorer.roll(7)
60
+ assert.equal(17, scorer.score())
50
61
  end)
51
62
 
52
- it('should allow a game with all open frames', function()
53
- roll_n_times({ 6, 3 }, 10)
54
- assert.equal(90, scorer.score())
63
+ it('should score a strike as 10 points when the next frame earns no points', function()
64
+ scorer.roll(10)
65
+ roll_n_times(0, 18)
66
+ assert.equal(10, scorer.score())
55
67
  end)
56
68
 
57
- it('should correctly score a strike that is not on the last frame', function()
69
+ it('should score the next two rolls after a strike as double', function()
58
70
  scorer.roll(10)
59
71
  scorer.roll(5)
60
72
  scorer.roll(3)
@@ -80,17 +92,26 @@ describe('bowling', function()
80
92
  assert.equal(18, scorer.score())
81
93
  end)
82
94
 
83
- it('should allow fill balls to be strikes when the final frame is a strike', function()
95
+ it('should not allow a bonus roll after rolling a spare after a strike on the last frame', function()
84
96
  roll_n_times(0, 18)
85
97
  scorer.roll(10)
86
- scorer.roll(10)
87
- scorer.roll(10)
98
+ scorer.roll(7)
99
+ scorer.roll(3)
100
+ assert.equal(20, scorer.score())
101
+ end)
102
+
103
+ it('should not allow bonus rolls for strikes rolled with fill balls from a strike', function()
104
+ roll_n_times(0, 18)
105
+ roll_n_times(10, 3)
88
106
  assert.equal(30, scorer.score())
89
107
  end)
90
108
 
91
- it('should not allow the game to be scored before fill balls have been played', function()
92
- roll_n_times(10, 10)
93
- assert.has_error(function() scorer.score() end)
109
+ it('should not allow bonus rolls for strikes rolled the fill ball from a spare', function()
110
+ roll_n_times(0, 18)
111
+ scorer.roll(7)
112
+ scorer.roll(3)
113
+ scorer.roll(10)
114
+ assert.equal(20, scorer.score())
94
115
  end)
95
116
 
96
117
  it('should be able to score a perfect game', function()
@@ -98,32 +119,55 @@ describe('bowling', function()
98
119
  assert.equal(300, scorer.score())
99
120
  end)
100
121
 
101
- it('should correctly score a spare that is not on the last frame', function()
102
- scorer.roll(5)
103
- scorer.roll(5)
104
- scorer.roll(3)
105
- scorer.roll(4)
106
- roll_n_times(0, 16)
107
- assert.equal(20, scorer.score())
122
+ it('should not allow a roll with negative pins', function()
123
+ assert.has_error(function() scorer.roll(-1) end)
108
124
  end)
109
125
 
110
- it('should correctly score multiple spares in a row', function()
126
+ it('should not allow a roll better than a strike', function()
127
+ assert.has_error(function() scorer.roll(11) end)
128
+ end)
129
+
130
+ it('should not allow two rolls in a frame to exceed 10 pins', function()
111
131
  scorer.roll(5)
132
+ assert.has_error(function() scorer.roll(6) end)
133
+ end)
134
+
135
+ it('should not allow fill balls after a strike in the final frame to score more than 10 points', function()
136
+ roll_n_times(0, 18)
137
+ scorer.roll(10)
112
138
  scorer.roll(5)
113
- scorer.roll(3)
114
- scorer.roll(7)
115
- scorer.roll(4)
116
- scorer.roll(1)
117
- roll_n_times(0, 14)
118
- assert.equal(32, scorer.score())
139
+ assert.has_error(function() scorer.roll(6) end)
119
140
  end)
120
141
 
121
- it('should allow a fill ball to be rolled if the last frame is a spare', function()
142
+ it('should not allow the score to be taken at the beginning of the game', function()
143
+ assert.has_error(function() scorer.score() end)
144
+ end)
145
+
146
+ it('should not allow the score to be taken before 10 frames have been played', function()
147
+ roll_n_times(0, 19)
148
+ assert.has_error(function() scorer.score() end)
149
+ end)
150
+
151
+ it('should not allow more rolls after 10 frames have been played', function()
152
+ roll_n_times(0, 20)
153
+ assert.has_error(function() scorer.roll(0) end)
154
+ end)
155
+
156
+ it('should not allow the game to be scored before either fill ball for a strike in the final frame', function()
157
+ roll_n_times(10, 10)
158
+ assert.has_error(function() scorer.score() end)
159
+ end)
160
+
161
+ it('should not allow the game to be scored before either both fill balls for a strike in the final frame', function()
162
+ roll_n_times(10, 11)
163
+ assert.has_error(function() scorer.score() end)
164
+ end)
165
+
166
+ it('should not allow the game to be scored before either the fill ball for a spare in the final frame', function()
122
167
  roll_n_times(0, 18)
123
- scorer.roll(9)
124
- scorer.roll(1)
125
168
  scorer.roll(7)
126
- assert.equal(17, scorer.score())
169
+ scorer.roll(3)
170
+ assert.has_error(function() scorer.score() end)
127
171
  end)
128
172
 
129
173
  it('should allow multiple independent scorers to be created', function()
@@ -22,6 +22,7 @@ return function()
22
22
  table.insert(current, pins)
23
23
 
24
24
  if #current == 3 and strike() then
25
+ assert(current[2] == 10 or current[2] + current[3] <= 10, 'illegal roll')
25
26
  table.insert(frames, current[1] + current[2] + current[3])
26
27
  table.remove(current, 1)
27
28
  end
@@ -33,7 +34,9 @@ return function()
33
34
  end
34
35
 
35
36
  if #frames < 10 and #current == 2 and not spare() and not strike() then
36
- table.insert(frames, current[1] + current[2])
37
+ local total = current[1] + current[2]
38
+ assert(total <= 10, 'illegal roll')
39
+ table.insert(frames, total)
37
40
  table.remove(current, 1)
38
41
  table.remove(current, 1)
39
42
  end
@@ -3,36 +3,6 @@
3
3
  "language": "Objective-C",
4
4
  "repository": "https://github.com/exercism/xobjective-c",
5
5
  "active": true,
6
- "problems": [
7
- "hello-world"
8
- ,"bob"
9
- ,"hamming"
10
- ,"word-count"
11
- ,"anagram"
12
- ,"nucleotide-count"
13
- ,"phone-number"
14
- ,"grade-school"
15
- ,"robot-name"
16
- ,"leap"
17
- ,"etl"
18
- ,"perfect-numbers"
19
- ,"space-age"
20
- ,"all-your-base"
21
- ,"allergies"
22
- ,"roman-numerals"
23
- ,"sum-of-multiples"
24
- ,"gigasecond"
25
- ,"meetup"
26
- ,"triangle"
27
- ,"scrabble-score"
28
- ,"difference-of-squares"
29
- ,"raindrops"
30
- ,"clock"
31
- ,"secret-handshake"
32
- ,"acronym"
33
- ,"run-length-encoding"
34
- ,"largest-series-product"
35
- ],
36
6
  "exercises": [
37
7
  {
38
8
  "difficulty": 1,
@@ -240,6 +210,15 @@
240
210
  "Transforming"
241
211
  ]
242
212
  },
213
+ {
214
+ "difficulty": 4,
215
+ "slug": "pangram",
216
+ "topics": [
217
+ "Strings",
218
+ "Searching",
219
+ "Transforming"
220
+ ]
221
+ },
243
222
  {
244
223
  "difficulty": 5,
245
224
  "slug": "roman-numerals",
@@ -0,0 +1,7 @@
1
+ #import <Foundation/Foundation.h>
2
+
3
+ @interface Pangram : NSObject
4
+
5
+ + (BOOL)isPangram:(NSString *)text;
6
+
7
+ @end
@@ -0,0 +1,21 @@
1
+ #import "PangramExample.h"
2
+
3
+ @implementation Pangram
4
+
5
+ + (BOOL)isPangram:(NSString *)text {
6
+ NSString *lowercasedText = [[text stringByApplyingTransform:NSStringTransformStripCombiningMarks reverse:NO] lowercaseString];
7
+ NSString *letters = @"abcdefghijklmnopqrstuvwxyz";
8
+
9
+ for (int i = 0; i < [letters length]; i++) {
10
+ unichar character = [letters characterAtIndex:i];
11
+ NSString *letter = [NSString stringWithFormat:@"%c", character];
12
+
13
+ if (![lowercasedText containsString:letter]) {
14
+ return NO;
15
+ }
16
+ }
17
+
18
+ return YES;
19
+ }
20
+
21
+ @end
@@ -0,0 +1,51 @@
1
+ #import <XCTest/XCTest.h>
2
+
3
+ #if __has_include("PangramExample.h")
4
+ # import "PangramExample.h"
5
+ # else
6
+ # import "Pangram.h"
7
+ #endif
8
+
9
+ @interface PangramTest : XCTestCase
10
+
11
+ @end
12
+
13
+ @implementation PangramTest
14
+
15
+ - (void)testSentenceEmpty {
16
+ XCTAssertFalse([Pangram isPangram:@""]);
17
+ }
18
+
19
+ - (void)test_pangram_with_only_lower_case {
20
+ XCTAssertTrue([Pangram isPangram:@"the quick brown fox jumps over the lazy dog"]);
21
+ }
22
+
23
+ - (void)testMissingCharacterX {
24
+ XCTAssertFalse([Pangram isPangram:@"a quick movement of the enemy will jeopardize five gunboats"]);
25
+ }
26
+
27
+ - (void)testAnotherMissingCharacterX {
28
+ XCTAssertFalse([Pangram isPangram:@"the quick brown fish jumps over the lazy dog"]);
29
+ }
30
+
31
+ - (void)testPangramWithUnderscores {
32
+ XCTAssertTrue([Pangram isPangram:@"the_quick_brown_fox_jumps_over_the_lazy_dog"]);
33
+ }
34
+
35
+ - (void)testPangramWithNumbers {
36
+ XCTAssertTrue([Pangram isPangram:@"the 1 quick brown fox jumps over the 2 lazy dogs"]);
37
+ }
38
+
39
+ - (void)testMissingLettersReplacedByNumbers {
40
+ XCTAssertFalse([Pangram isPangram:@"7h3 qu1ck brown fox jumps ov3r 7h3 lazy dog"]);
41
+ }
42
+
43
+ - (void)testPangramWithMixedCaseAndPunctuation {
44
+ XCTAssertTrue([Pangram isPangram:@"Five quacking Zephyrs jolt my wax bed."]);
45
+ }
46
+
47
+ - (void)testPangramWithNonAsciiCharacters {
48
+ XCTAssertTrue([Pangram isPangram:@"Victor jagt zwölf Boxkämpfer quer über den großen Sylter Deich."]);
49
+ }
50
+
51
+ @end
@@ -69,6 +69,8 @@
69
69
  E99D1D831D5533D80006A303 /* SumOfMultiplesTest.m in Sources */ = {isa = PBXBuildFile; fileRef = E99D1D821D5533D80006A303 /* SumOfMultiplesTest.m */; };
70
70
  E9A7B2F71DA5AC37009056B6 /* LargestSeriesProductExample.m in Sources */ = {isa = PBXBuildFile; fileRef = E9A7B2F61DA5AC37009056B6 /* LargestSeriesProductExample.m */; };
71
71
  E9A7B2F91DA5AC55009056B6 /* LargestSeriesProductTest.m in Sources */ = {isa = PBXBuildFile; fileRef = E9A7B2F81DA5AC55009056B6 /* LargestSeriesProductTest.m */; };
72
+ E9B345F81DB93822006EFBE2 /* PangramExample.m in Sources */ = {isa = PBXBuildFile; fileRef = E9B345F71DB93822006EFBE2 /* PangramExample.m */; };
73
+ E9B345FA1DB93839006EFBE2 /* PangramTest.m in Sources */ = {isa = PBXBuildFile; fileRef = E9B345F91DB93839006EFBE2 /* PangramTest.m */; };
72
74
  E9C1C0231D9D993E0015E86E /* SecretHandshakeExample.m in Sources */ = {isa = PBXBuildFile; fileRef = E9C1C0221D9D993E0015E86E /* SecretHandshakeExample.m */; };
73
75
  E9C1C0251D9D99620015E86E /* SecretHandshakeTest.m in Sources */ = {isa = PBXBuildFile; fileRef = E9C1C0241D9D99620015E86E /* SecretHandshakeTest.m */; };
74
76
  E9C1C0291D9DB16B0015E86E /* AcronymExample.m in Sources */ = {isa = PBXBuildFile; fileRef = E9C1C0281D9DB16B0015E86E /* AcronymExample.m */; };
@@ -154,6 +156,9 @@
154
156
  E9A7B2F51DA5AC37009056B6 /* LargestSeriesProductExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LargestSeriesProductExample.h; path = "../../exercises/largest-series-product/LargestSeriesProductExample.h"; sourceTree = "<group>"; };
155
157
  E9A7B2F61DA5AC37009056B6 /* LargestSeriesProductExample.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LargestSeriesProductExample.m; path = "../../exercises/largest-series-product/LargestSeriesProductExample.m"; sourceTree = "<group>"; };
156
158
  E9A7B2F81DA5AC55009056B6 /* LargestSeriesProductTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LargestSeriesProductTest.m; path = "../../exercises/largest-series-product/LargestSeriesProductTest.m"; sourceTree = "<group>"; };
159
+ E9B345F61DB93822006EFBE2 /* PangramExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PangramExample.h; path = ../../exercises/pangram/PangramExample.h; sourceTree = "<group>"; };
160
+ E9B345F71DB93822006EFBE2 /* PangramExample.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PangramExample.m; path = ../../exercises/pangram/PangramExample.m; sourceTree = "<group>"; };
161
+ E9B345F91DB93839006EFBE2 /* PangramTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PangramTest.m; path = ../../exercises/pangram/PangramTest.m; sourceTree = "<group>"; };
157
162
  E9C1C0211D9D993E0015E86E /* SecretHandshakeExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecretHandshakeExample.h; path = "../../exercises/secret-handshake/SecretHandshakeExample.h"; sourceTree = "<group>"; };
158
163
  E9C1C0221D9D993E0015E86E /* SecretHandshakeExample.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SecretHandshakeExample.m; path = "../../exercises/secret-handshake/SecretHandshakeExample.m"; sourceTree = "<group>"; };
159
164
  E9C1C0241D9D99620015E86E /* SecretHandshakeTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SecretHandshakeTest.m; path = "../../exercises/secret-handshake/SecretHandshakeTest.m"; sourceTree = "<group>"; };
@@ -198,6 +203,7 @@
198
203
  E9E8B6F11D519E120012F12C /* Leap */,
199
204
  E92FCC0A1D78F2AA00061017 /* Meetup */,
200
205
  E9E8B6F21D519E180012F12C /* NucleotideCount */,
206
+ E9B345F51DB937E5006EFBE2 /* Pangram */,
201
207
  E9E8B6F31D519E200012F12C /* PerfectNumbers */,
202
208
  E9E8B6F41D519E270012F12C /* PhoneNumber */,
203
209
  E9381D491D8F293C003F22A1 /* Raindrops */,
@@ -321,6 +327,16 @@
321
327
  name = LargestSeriesProduct;
322
328
  sourceTree = "<group>";
323
329
  };
330
+ E9B345F51DB937E5006EFBE2 /* Pangram */ = {
331
+ isa = PBXGroup;
332
+ children = (
333
+ E9B345F61DB93822006EFBE2 /* PangramExample.h */,
334
+ E9B345F71DB93822006EFBE2 /* PangramExample.m */,
335
+ E9B345F91DB93839006EFBE2 /* PangramTest.m */,
336
+ );
337
+ name = Pangram;
338
+ sourceTree = "<group>";
339
+ };
324
340
  E9C1C0201D9D98B80015E86E /* SecretHandshake */ = {
325
341
  isa = PBXGroup;
326
342
  children = (
@@ -621,6 +637,7 @@
621
637
  E9381D541D8F2DE1003F22A1 /* ClockTest.m in Sources */,
622
638
  1EFACAB41CCCAF3D006F2E69 /* PerfectNumbersTest.m in Sources */,
623
639
  E9FDCA191D5407D2004EE8DB /* RomanNumeralsExample.m in Sources */,
640
+ E9B345F81DB93822006EFBE2 /* PangramExample.m in Sources */,
624
641
  1EFACAAE1CCCAF3D006F2E69 /* HelloWorldTest.m in Sources */,
625
642
  1EFACAB21CCCAF3D006F2E69 /* NucleotideCountTest.m in Sources */,
626
643
  E907D0CC1D6B734800106C42 /* GigasecondTest.m in Sources */,
@@ -648,6 +665,7 @@
648
665
  E947A4DE1D81FE0F00633720 /* TriangleExample.m in Sources */,
649
666
  1EFACAAC1CCCAF3D006F2E69 /* HammingTest.m in Sources */,
650
667
  1EFACAA61CCCAF3D006F2E69 /* BobTest.m in Sources */,
668
+ E9B345FA1DB93839006EFBE2 /* PangramTest.m in Sources */,
651
669
  E9A7B2F91DA5AC55009056B6 /* LargestSeriesProductTest.m in Sources */,
652
670
  1EFACAAF1CCCAF3D006F2E69 /* LeapExample.m in Sources */,
653
671
  E9C1C0251D9D99620015E86E /* SecretHandshakeTest.m in Sources */,
@@ -4,7 +4,52 @@ Exercism Exercises in OCaml
4
4
 
5
5
  ## Contributing Guide
6
6
 
7
- Please see the [contributing guide](https://github.com/exercism/x-api/blob/master/CONTRIBUTING.md#the-exercise-data)
7
+ Contributions to the OCaml track (or any other part of Exercism) are very welcome!
8
+
9
+ Please see the [contributing guide](https://github.com/exercism/x-common/blob/master/CONTRIBUTING.md) for overall guidance. The below
10
+ notes contain a few details specific to Ocaml.
11
+
12
+ ## Prerequisites
13
+
14
+ The OCaml track assumes installation of OCaml version 4.03.0, and installation of Core, OUnit, and React (for the Hangman exercise).
15
+ Assuming you have opam, these can be installed with
16
+ ```bash
17
+ opam install core ounit react
18
+ ```
19
+
20
+ ## Running Tests
21
+
22
+ To run all the tests, type `make` from the top level xocaml directory.
23
+
24
+ To run tests for an individual exercise, `make test-assignment ASSIGNMENT=luhn`
25
+
26
+ ## Adding an Exercise
27
+
28
+ The [contributing guide](https://github.com/exercism/x-common/blob/master/CONTRIBUTING.md) provides guidance on
29
+ how to add a new exercise, or port an existing exercise from another language track. This is a brief guide, with specifics for the OCaml stream.
30
+
31
+ Firstly, register the exercise in [config json](https://github.com/exercism/x-common/blob/master/CONTRIBUTING.md#configjson). The name of the exercise should go in the "slug" entry.
32
+
33
+ Then, write the exercise tests & proof of concept implementation.
34
+ A folder layout for an exercise called "ocaml-exercise" is below.
35
+
36
+ ```
37
+ └── exercises
38
+ └── ocaml-exercise
39
+ ├── .merlin (provided IDE assistance - copy this from any of the other Ocaml exercises)
40
+ ├── example.ml (a proof of concept implementation)
41
+ ├── ocaml_exercise.mli (the interface definition for the exercise)
42
+ ├── HINTS.md (additional hints to anyone trying the exercise - optional)
43
+ ├── Makefile (standard - copy this from any of the other Ocaml exercises)
44
+ ├── test.ml (unit tests)
45
+ ```
46
+ In this example, the Makefile would look for an implementation in ocaml_exercise.ml - as it matches the .mli file name. When developing it is easier to create and edit ocaml_exercise.ml, but the code should be copied to example.ml prior to submitting a pull request (and ocaml_exercise.ml should not be submitted).
47
+
48
+ All pull requests are run through a Travis CI build, which compiles and runs tests.
49
+
50
+ ## Feedback
51
+
52
+ If you find this documentation is inaccurate or incomplete, or can be improved in any way, please don't hesitate to raise an [issue](https://github.com/exercism/xocaml/issues) or submit a pull request.
8
53
 
9
54
  ## License
10
55
 
@@ -1,9 +1,14 @@
1
- For running the tests provided, you will need `Opam` and `Core`. Consult [opam](https://opam.ocaml.org) website for instuctions on how to install for your OS. Once `opam` is installed open a terminal window and run the following command to install core:
1
+
2
+ ## Getting Started
3
+ For installation and learning resources, refer to the
4
+ [exercism help page](http://exercism.io/languages/ocaml).
5
+
6
+ ## Installation
7
+ To work on the exercises, you will need `Opam` and `Core`. Consult [opam](https://opam.ocaml.org) website for instructions on how to install for your OS. Once `opam` is installed open a terminal window and run the following command to install core:
2
8
 
3
9
  opam install core
4
10
 
5
11
  ## Running Tests
6
-
7
12
  Because OCaml is a compiled language you need to compile your submission and the test code before you can run the tests. Compile with
8
13
 
9
14
  ```bash
@@ -21,3 +26,17 @@ Alternatively just type
21
26
  ```bash
22
27
  make
23
28
  ```
29
+
30
+ ## Interactive Shell
31
+ `utop` is a command line program which allows you to run Ocaml code interactively. The easiest way to install it is via opam:
32
+ ```bash
33
+ opam install utop
34
+ ```
35
+ Consult [utop](https://github.com/diml/utop/blob/master/README.md) for more detail.
36
+
37
+ ## Feedback, Issues, Pull Requests
38
+ The [exercism/xocaml](https://github.com/exercism/xocaml) repository on
39
+ GitHub is the home for all of the Ocaml exercises.
40
+
41
+ If you have feedback about an exercise, or want to help implementing a new
42
+ one, head over there and create an issue. We'll do our best to help you!