trackler 2.0.0.1 → 2.0.0.2

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/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!