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
@@ -0,0 +1,237 @@
1
+ import org.scalatest.{FunSuite, Matchers}
2
+
3
+ class BowlingSuite extends FunSuite with Matchers {
4
+ // returns the final score of a bowling game
5
+ test("should be able to score a game with all zeros") {
6
+ val score = List(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
7
+ score match {
8
+ case Right(n) => assert(n == 0)
9
+ case Left(_) => fail("should be able to score a game with all zeros")
10
+ }
11
+ }
12
+
13
+ test("should be able to score a game with no strikes or spares") {
14
+ pending
15
+ val score = List(3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
16
+ score match {
17
+ case Right(n) => assert(n == 90)
18
+ case Left(_) => fail("should be able to score a game with no strikes or spares")
19
+ }
20
+ }
21
+
22
+ test("a spare followed by zeros is worth ten points") {
23
+ pending
24
+ val score = List(6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
25
+ score match {
26
+ case Right(n) => assert(n == 10)
27
+ case Left(_) => fail("a spare followed by zeros is worth ten points")
28
+ }
29
+ }
30
+
31
+ test("points scored in the roll after a spare are counted twice") {
32
+ pending
33
+ val score = List(6, 4, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
34
+ score match {
35
+ case Right(n) => assert(n == 16)
36
+ case Left(_) => fail("points scored in the roll after a spare are counted twice")
37
+ }
38
+ }
39
+
40
+ test("consecutive spares each get a one roll bonus") {
41
+ pending
42
+ val score = List(5, 5, 3, 7, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
43
+ score match {
44
+ case Right(n) => assert(n == 31)
45
+ case Left(_) => fail("consecutive spares each get a one roll bonus")
46
+ }
47
+ }
48
+
49
+ test("a spare in the last frame gets a one roll bonus that is counted once") {
50
+ pending
51
+ val score = List(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3, 7).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
52
+ score match {
53
+ case Right(n) => assert(n == 17)
54
+ case Left(_) => fail("a spare in the last frame gets a one roll bonus that is counted once")
55
+ }
56
+ }
57
+
58
+ test("a strike earns ten points in a frame with a single roll") {
59
+ pending
60
+ val score = List(10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
61
+ score match {
62
+ case Right(n) => assert(n == 10)
63
+ case Left(_) => fail("a strike earns ten points in a frame with a single roll")
64
+ }
65
+ }
66
+
67
+ test("points scored in the two rolls after a strike are counted twice as a bonus") {
68
+ pending
69
+ val score = List(10, 5, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
70
+ score match {
71
+ case Right(n) => assert(n == 26)
72
+ case Left(_) => fail("points scored in the two rolls after a strike are counted twice as a bonus")
73
+ }
74
+ }
75
+
76
+ test("consecutive strikes each get the two roll bonus") {
77
+ pending
78
+ val score = List(10, 10, 10, 5, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
79
+ score match {
80
+ case Right(n) => assert(n == 81)
81
+ case Left(_) => fail("consecutive strikes each get the two roll bonus")
82
+ }
83
+ }
84
+
85
+ test("a strike in the last frame gets a two roll bonus that is counted once") {
86
+ pending
87
+ val score = List(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 7, 1).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
88
+ score match {
89
+ case Right(n) => assert(n == 18)
90
+ case Left(_) => fail("a strike in the last frame gets a two roll bonus that is counted once")
91
+ }
92
+ }
93
+
94
+ test("rolling a spare with the two roll bonus does not get a bonus roll") {
95
+ pending
96
+ val score = List(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 7, 3).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
97
+ score match {
98
+ case Right(n) => assert(n == 20)
99
+ case Left(_) => fail("rolling a spare with the two roll bonus does not get a bonus roll")
100
+ }
101
+ }
102
+
103
+ test("strikes with the two roll bonus do not get bonus rolls") {
104
+ pending
105
+ val score = List(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
106
+ score match {
107
+ case Right(n) => assert(n == 30)
108
+ case Left(_) => fail("strikes with the two roll bonus do not get bonus rolls")
109
+ }
110
+ }
111
+
112
+ test("a strike with the one roll bonus after a spare in the last frame does not get a bonus") {
113
+ pending
114
+ val score = List(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3, 10).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
115
+ score match {
116
+ case Right(n) => assert(n == 20)
117
+ case Left(_) => fail("a strike with the one roll bonus after a spare in the last frame does not get a bonus")
118
+ }
119
+ }
120
+
121
+ test("all strikes is a perfect game") {
122
+ pending
123
+ val score = List(10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
124
+ score match {
125
+ case Right(n) => assert(n == 300)
126
+ case Left(_) => fail("all strikes is a perfect game")
127
+ }
128
+ }
129
+
130
+ test("rolls can not score negative points") {
131
+ pending
132
+ val score = List(-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
133
+ score match {
134
+ case Right(_) => fail("Unexpected score returned. Failure expected")
135
+ case Left(_) =>
136
+ }
137
+ }
138
+
139
+ test("a roll can not score more than 10 points") {
140
+ pending
141
+ val score = List(11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
142
+ score match {
143
+ case Right(_) => fail("Unexpected score returned. Failure expected")
144
+ case Left(_) =>
145
+ }
146
+ }
147
+
148
+ test("two rolls in a frame can not score more than 10 points") {
149
+ pending
150
+ val score = List(5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
151
+ score match {
152
+ case Right(_) => fail("Unexpected score returned. Failure expected")
153
+ case Left(_) =>
154
+ }
155
+ }
156
+
157
+ test("two bonus rolls after a strike in the last frame can not score more than 10 points") {
158
+ pending
159
+ val score = List(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 5, 6).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
160
+ score match {
161
+ case Right(_) => fail("Unexpected score returned. Failure expected")
162
+ case Left(_) =>
163
+ }
164
+ }
165
+
166
+ test("two bonus rolls after a strike in the last frame can score more than 10 points if one is a strike") {
167
+ pending
168
+ val score = List(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 6).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
169
+ score match {
170
+ case Right(n) => assert(n == 26)
171
+ case Left(_) => fail("two bonus rolls after a strike in the last frame can score more than 10 points if one is a strike")
172
+ }
173
+ }
174
+
175
+ test("the second bonus rolls after a strike in the last frame can not be a strike if the first one is not a strike") {
176
+ pending
177
+ val score = List(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 6, 10).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
178
+ score match {
179
+ case Right(_) => fail("Unexpected score returned. Failure expected")
180
+ case Left(_) =>
181
+ }
182
+ }
183
+
184
+ test("an unstarted game can not be scored") {
185
+ pending
186
+ val score = List().foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
187
+ score match {
188
+ case Right(_) => fail("Unexpected score returned. Failure expected")
189
+ case Left(_) =>
190
+ }
191
+ }
192
+
193
+ test("an incomplete game can not be scored") {
194
+ pending
195
+ val score = List(0, 0).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
196
+ score match {
197
+ case Right(_) => fail("Unexpected score returned. Failure expected")
198
+ case Left(_) =>
199
+ }
200
+ }
201
+
202
+ test("a game with more than ten frames can not be scored") {
203
+ pending
204
+ val score = List(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
205
+ score match {
206
+ case Right(_) => fail("Unexpected score returned. Failure expected")
207
+ case Left(_) =>
208
+ }
209
+ }
210
+
211
+ test("bonus rolls for a strike in the last frame must be rolled before score can be calculated") {
212
+ pending
213
+ val score = List(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
214
+ score match {
215
+ case Right(_) => fail("Unexpected score returned. Failure expected")
216
+ case Left(_) =>
217
+ }
218
+ }
219
+
220
+ test("both bonus rolls for a strike in the last frame must be rolled before score can be calculated") {
221
+ pending
222
+ val score = List(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
223
+ score match {
224
+ case Right(_) => fail("Unexpected score returned. Failure expected")
225
+ case Left(_) =>
226
+ }
227
+ }
228
+
229
+ test("bonus roll for a spare in the last frame must be rolled before score can be calculated") {
230
+ pending
231
+ val score = List(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
232
+ score match {
233
+ case Right(_) => fail("Unexpected score returned. Failure expected")
234
+ case Left(_) =>
235
+ }
236
+ }
237
+ }
@@ -7,204 +7,254 @@ class ClockTest extends FlatSpec with Matchers {
7
7
  }
8
8
 
9
9
  it should "construct from minutes" in {
10
+ pending
10
11
  Clock(3).toString should be ("00:03")
11
12
  }
12
13
 
13
14
  it should "implement equals" in {
15
+ pending
14
16
  Clock(15, 37) should be (Clock(15, 37))
15
17
  Clock(15, 37) should not be Clock(15, 36)
16
18
  }
17
19
 
18
20
  it should "support wraparound" in {
21
+ pending
19
22
  Clock(24, 0) should be (Clock(0, 0))
20
23
  Clock(25, 0) should be (Clock(1, 0))
21
24
  }
22
25
 
23
26
  it should "handle hour rolls over continuously" in {
27
+ pending
24
28
  Clock(100, 0) should be (Clock(4, 0))
25
29
  }
26
30
 
27
31
  it should "implement 60 min as the next hour" in {
32
+ pending
28
33
  Clock(1, 60) should be (Clock(2, 0))
29
34
  }
30
35
 
31
36
  it should "construct consistently between constructors" in {
37
+ pending
32
38
  Clock(60) should be (Clock(1, 0))
33
39
  }
34
40
 
35
41
  it should "support rolling over minutes" in {
42
+ pending
36
43
  Clock(0, 160) should be (Clock(2, 40))
37
44
  }
38
45
 
39
46
  it should "handle minutes rolling over consistently" in {
47
+ pending
40
48
  Clock(0, 1723) should be (Clock(4, 43))
41
49
  }
42
50
 
43
51
  it should "support rolling over both hours and minutes" in {
52
+ pending
44
53
  Clock(25, 160) should be (Clock(3, 40))
45
54
  }
46
55
 
47
56
  it should "handle hours and minutes rolling over consistently" in {
57
+ pending
48
58
  Clock(201, 3001) should be (Clock(11, 1))
49
59
  }
50
60
 
51
61
  it should "handle hours and minutes rolling over to midnight" in {
62
+ pending
52
63
  Clock(72, 8640) should be (Clock(0, 0))
53
64
  }
54
65
 
55
66
  it should "handle negative hour" in {
67
+ pending
56
68
  Clock(-1, 15) should be (Clock(23, 15))
57
69
  }
58
70
 
59
71
  it should "handle rolling over negative hour" in {
72
+ pending
60
73
  Clock(-25, 0) should be (Clock(23, 0))
61
74
  }
62
75
 
63
76
  it should "handle negative hours rolling over consistently" in {
77
+ pending
64
78
  Clock(-91, 0) should be (Clock(5, 0))
65
79
  }
66
80
 
67
81
  it should "handle negative minute" in {
82
+ pending
68
83
  Clock(1, -40) should be (Clock(0, 20))
69
84
  }
70
85
 
71
86
  it should "handle rolling over negative minute" in {
87
+ pending
72
88
  Clock(1, -160) should be (Clock(22, 20))
73
89
  }
74
90
 
75
91
  it should "handle negative minutes rolling over consistently" in {
92
+ pending
76
93
  Clock(1, -4820) should be (Clock(16, 40))
77
94
  }
78
95
 
79
96
  it should "handle negative hour and minutes roll over" in {
97
+ pending
80
98
  Clock(-25, -160) should be (Clock(20, 20))
81
99
  }
82
100
 
83
101
  it should "handle negative hour and minutes rolling over consistently" in {
102
+ pending
84
103
  Clock(-121, -5810) should be (Clock(22, 10))
85
104
  }
86
105
 
87
106
  it should "add minutes" in {
107
+ pending
88
108
  Clock(10, 0) + Clock(3) should be (Clock(10, 3))
89
109
  }
90
110
 
91
111
  it should "add no minutes" in {
112
+ pending
92
113
  Clock(6, 41) + Clock(0) should be (Clock(6, 41))
93
114
  }
94
115
 
95
116
  it should "add to next hour" in {
117
+ pending
96
118
  Clock(0, 45) + Clock(40) should be (Clock(1, 25))
97
119
  }
98
120
 
99
121
  it should "add more than one hour" in {
122
+ pending
100
123
  Clock(10, 0) + Clock(61) should be (Clock(11, 1))
101
124
  }
102
125
 
103
126
  it should "add more than two hours with carry" in {
127
+ pending
104
128
  Clock(0, 45) + Clock(160) should be (Clock(3, 25))
105
129
  }
106
130
 
107
131
  it should "add across midnight" in {
132
+ pending
108
133
  Clock(23, 59) + Clock(2) should be (Clock(0, 1))
109
134
  }
110
135
 
111
136
  it should "add more than one day (1500 min == 25 hours)" in {
137
+ pending
112
138
  Clock(5, 32) + Clock(1500) should be (Clock(6, 32))
113
139
  }
114
140
 
115
141
  it should "add more than 2 days" in {
142
+ pending
116
143
  Clock(1, 1) + Clock(3500) should be (Clock(11, 21))
117
144
  }
118
145
 
119
146
  it should "subtract minutes" in {
147
+ pending
120
148
  Clock(10, 3) - Clock(3) should be (Clock(10, 0))
121
149
  }
122
150
 
123
151
  it should "subtract to previous hour" in {
152
+ pending
124
153
  Clock(10, 3) - Clock(30) should be (Clock(9, 33))
125
154
  }
126
155
 
127
156
  it should "subtract more than an hour" in {
157
+ pending
128
158
  Clock(10, 3) - Clock(70) should be (Clock(8, 53))
129
159
  }
130
160
 
131
161
  it should "subtract across midnight" in {
162
+ pending
132
163
  Clock(0, 3) - Clock(4) should be (Clock(23, 59))
133
164
  }
134
165
 
135
166
  it should "subtract more than two hours" in {
167
+ pending
136
168
  Clock(0, 0) - Clock(160) should be (Clock(21, 20))
137
169
  }
138
170
 
139
171
  it should "subtract more than two hours with borrow" in {
172
+ pending
140
173
  Clock(6, 15) - Clock(160) should be (Clock(3, 35))
141
174
  }
142
175
 
143
176
  it should "subtract more than one day (1500 min = 25 hrs)" in {
177
+ pending
144
178
  Clock(5, 32) - Clock(1500) should be (Clock(4, 32))
145
179
  }
146
180
 
147
181
  it should "subtract more than two days" in {
182
+ pending
148
183
  Clock(2, 20) - Clock(3000) should be (Clock(0, 20))
149
184
  }
150
185
 
151
186
  it should "handle equality of clocks with same time" in {
187
+ pending
152
188
  Clock(15, 37) should be (Clock(15, 37))
153
189
  }
154
190
 
155
191
  it should "handle equality of clocks that are one minute apart" in {
192
+ pending
156
193
  Clock(15, 36) should not be (Clock(15, 37))
157
194
  }
158
195
 
159
196
  it should "handle equality of clocks that are one hour apart" in {
197
+ pending
160
198
  Clock(14, 37) should not be (Clock(15, 37))
161
199
  }
162
200
 
163
201
  it should "handle equality of clocks with hour overflow" in {
202
+ pending
164
203
  Clock(10, 37) should be (Clock(34, 37))
165
204
  }
166
205
 
167
206
  it should "handle equality of clocks with hour overflow by several days" in {
207
+ pending
168
208
  Clock(3, 11) should be (Clock(99, 11))
169
209
  }
170
210
 
171
211
  it should "handle equality of clocks with negative hour" in {
212
+ pending
172
213
  Clock(22, 40) should be (Clock(-2, 40))
173
214
  }
174
215
 
175
216
  it should "handle equality of clocks with negative hour that wraps" in {
217
+ pending
176
218
  Clock(17, 3) should be (Clock(-31, 3))
177
219
  }
178
220
 
179
221
  it should "handle equality of clocks with negative hour that wraps multiple times" in {
222
+ pending
180
223
  Clock(13, 49) should be (Clock(-83, 49))
181
224
  }
182
225
 
183
226
  it should "handle equality of clocks with minute overflow" in {
227
+ pending
184
228
  Clock(0, 1) should be (Clock(0, 1441))
185
229
  }
186
230
 
187
231
  it should "handle equality of clocks with minute overflow by several days" in {
232
+ pending
188
233
  Clock(2, 2) should be (Clock(2, 4322))
189
234
  }
190
235
 
191
236
  it should "handle equality of clocks with negative minute" in {
237
+ pending
192
238
  Clock(2, 40) should be (Clock(3, -20))
193
239
  }
194
240
 
195
241
  it should "handle equality of clocks with negative minute that wraps" in {
242
+ pending
196
243
  Clock(4, 10) should be (Clock(5, -1490))
197
244
  }
198
245
 
199
246
  it should "handle equality of clocks with negative minute that wraps mutiple times" in {
247
+ pending
200
248
  Clock(6, 15) should be (Clock(6, -4305))
201
249
  }
202
250
 
203
251
  it should "handle equality of clocks with negative hours and minute" in {
252
+ pending
204
253
  Clock(7, 32) should be (Clock(-12, -268))
205
254
  }
206
255
 
207
256
  it should "handle equality of clocks with negative hours and minute that wrap" in {
257
+ pending
208
258
  Clock(18, 7) should be (Clock(-54, -11513))
209
259
  }
210
260
  }
@@ -0,0 +1,17 @@
1
+ # Connect
2
+
3
+ Determine a winner.
4
+
5
+ The Scala exercises assume an SBT project scheme. The exercise solution source should be placed within the exercise directory/src/main/scala. The exercise unit tests can be found within the exercise directory/src/test/scala.
6
+
7
+ To run the tests simply run the command `sbt test` in the exercise directory.
8
+
9
+ For more detailed info about the Scala track see the [help page](http://help.exercism.io/getting-started-with-scala.html).
10
+
11
+ ### Note
12
+
13
+ You may notice that some test cases seem unfair. However, they may be legitimately so. For example, it is common to give young or beginner players an extra n pieces at fixed positions on the board, so mismatched piece counts can occur in an otherwise fully legal game.
14
+
15
+ In any case, this exercise cares only about determining a winner for a game that can have a variety of parameters, like board length and extra pieces. It is not interested in any other state of the game, such as who moved where, when, or whose turn it is.
16
+
17
+ So don't be puzzled by those seemingly unfair games.
@@ -15,16 +15,19 @@ class ConnectTest extends FunSuite with Matchers {
15
15
  }
16
16
 
17
17
  test("black single item board") {
18
+ pending
18
19
  val lines = List("X")
19
20
  Connect(mkBoard(lines)).result should be (Some(Color.Black))
20
21
  }
21
22
 
22
23
  test("white single item board") {
24
+ pending
23
25
  val lines = List("O")
24
26
  Connect(mkBoard(lines)).result should be (Some(Color.White))
25
27
  }
26
28
 
27
29
  test("convoluted path") {
30
+ pending
28
31
  val lines = List(". X X . ."
29
32
  ," X . X . X"
30
33
  ," . X . X ."
@@ -34,6 +37,7 @@ class ConnectTest extends FunSuite with Matchers {
34
37
  }
35
38
 
36
39
  test("rectangle - black wins") {
40
+ pending
37
41
  val lines = List(". O . ."
38
42
  ," O X X X"
39
43
  ," O X O ."
@@ -43,6 +47,7 @@ class ConnectTest extends FunSuite with Matchers {
43
47
  }
44
48
 
45
49
  test("rectangle - white wins") {
50
+ pending
46
51
  val lines = List(". O . ."
47
52
  ," O X X X"
48
53
  ," O O O ."
@@ -52,6 +57,7 @@ class ConnectTest extends FunSuite with Matchers {
52
57
  }
53
58
 
54
59
  test("spiral - black wins") {
60
+ pending
55
61
  val lines = List("OXXXXXXXX"
56
62
  ,"OXOOOOOOO"
57
63
  ,"OXOXXXXXO"
@@ -65,6 +71,7 @@ class ConnectTest extends FunSuite with Matchers {
65
71
  }
66
72
 
67
73
  test("spiral - none") {
74
+ pending
68
75
  val lines = List("OXXXXXXXX"
69
76
  ,"OXOOOOOOO"
70
77
  ,"OXOXXXXXO"
@@ -6,36 +6,43 @@ class CrytpoSquareTest extends FlatSpec with Matchers {
6
6
  }
7
7
 
8
8
  it should "normalize uppercase to lowercase" in {
9
+ pending
9
10
  CryptoSquare().normalizePlaintext("1, 2, 3 GO!") should equal("123go")
10
11
  }
11
12
 
12
13
 
13
14
  it should "calc a square size for a perfect square" in {
15
+ pending
14
16
  CryptoSquare().squareSize("1234") should equal(2)
15
17
  CryptoSquare().squareSize("123456789") should equal(3)
16
18
  }
17
19
 
18
20
  it should "calc a square size when not a perfect square" in {
21
+ pending
19
22
  CryptoSquare().squareSize("123456789abc") should equal(4)
20
23
  CryptoSquare().squareSize("123456789abcd") should equal(4)
21
24
  }
22
25
 
23
26
  it should "not generate calc error when empty string" in {
27
+ pending
24
28
  CryptoSquare().squareSize("") should equal(0)
25
29
  }
26
30
 
27
31
 
28
32
  it should "build plaintext segments - all equal segment lengths" in {
33
+ pending
29
34
  CryptoSquare().plaintextSegments("Never vex thine heart with idle woes.") should
30
35
  equal(List("neverv", "exthin", "eheart", "withid", "lewoes"))
31
36
  }
32
37
 
33
38
  it should "build plaintext segments - last segment short" in {
39
+ pending
34
40
  CryptoSquare().plaintextSegments("ZOMG! ZOMBIES!!!") should
35
41
  equal(List("zomg", "zomb", "ies"))
36
42
  }
37
43
 
38
44
  it should "build cipher text" in {
45
+ pending
39
46
  CryptoSquare().ciphertext("Time is an illusion. Lunchtime doubly so.") should
40
47
  equal("tasneyinicdsmiohooelntuillibsuuml")
41
48
  CryptoSquare().ciphertext("We all know interspecies romance is weird.") should
@@ -43,6 +50,7 @@ class CrytpoSquareTest extends FlatSpec with Matchers {
43
50
  }
44
51
 
45
52
  it should "build normalized cipher text" in {
53
+ pending
46
54
  CryptoSquare().normalizedCiphertext("Madness, and then illumination.") should
47
55
  equal("msemo aanin dnin ndla etlt shui")
48
56
  CryptoSquare().normalizedCiphertext("If man was meant to stay on the ground " +
@@ -51,6 +59,7 @@ class CrytpoSquareTest extends FlatSpec with Matchers {
51
59
  }
52
60
 
53
61
  it should "not error on blank strings" in {
62
+ pending
54
63
  CryptoSquare().ciphertext("") should
55
64
  equal("")
56
65
  CryptoSquare().ciphertext(" ") should