trackler 1.0.0 → 1.0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (288) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +7 -0
  3. data/CHANGELOG.md +9 -1
  4. data/README.md +10 -0
  5. data/common/CONTRIBUTING.md +50 -2
  6. data/common/exercises/alphametics/canonical-data.json +10 -10
  7. data/common/exercises/markdown/canonical-data.json +4 -4
  8. data/common/exercises/pov/canonical-data.json +356 -0
  9. data/lib/trackler/version.rb +1 -1
  10. data/trackler.gemspec +1 -2
  11. data/tracks/c/config.json +11 -1
  12. data/tracks/c/exercises/binary-search/makefile +16 -0
  13. data/tracks/c/exercises/binary-search/src/example.c +21 -0
  14. data/tracks/c/exercises/binary-search/src/example.h +8 -0
  15. data/tracks/c/exercises/binary-search/test/test_binary_search.c +99 -0
  16. data/tracks/c/exercises/binary-search/test/vendor/unity.c +1300 -0
  17. data/tracks/c/exercises/binary-search/test/vendor/unity.h +274 -0
  18. data/tracks/c/exercises/binary-search/test/vendor/unity_internals.h +701 -0
  19. data/tracks/clojure/config.json +3 -2
  20. data/tracks/clojure/exercises/bank-account/project.clj +4 -0
  21. data/tracks/clojure/exercises/bank-account/src/example.clj +17 -0
  22. data/tracks/clojure/exercises/bank-account/test/bank_account_test.clj +44 -0
  23. data/tracks/clojure/exercises/isogram/project.clj +4 -0
  24. data/tracks/clojure/exercises/isogram/src/example.clj +5 -0
  25. data/tracks/clojure/exercises/isogram/test/isogram_test.clj +17 -0
  26. data/tracks/csharp/config.json +27 -87
  27. data/tracks/csharp/exercises/exercises.csproj +265 -1
  28. data/tracks/csharp/exercises/grep/Example.cs +114 -0
  29. data/tracks/csharp/exercises/grep/GrepTest.cs +376 -0
  30. data/tracks/csharp/exercises/paket.references +2 -1
  31. data/tracks/csharp/exercises/poker/Example.cs +96 -0
  32. data/tracks/csharp/exercises/poker/PokerTest.cs +171 -0
  33. data/tracks/csharp/exercises/sgf-parsing/Example.cs +61 -0
  34. data/tracks/csharp/exercises/sgf-parsing/SgfParsing.cs +13 -0
  35. data/tracks/csharp/exercises/sgf-parsing/SgfParsingTest.cs +158 -0
  36. data/tracks/csharp/paket.dependencies +2 -1
  37. data/tracks/csharp/paket.lock +72 -0
  38. data/tracks/ecmascript/exercises/simple-cipher/simple-cipher.spec.js +1 -1
  39. data/tracks/elisp/config.json +6 -1
  40. data/tracks/elisp/exercises/etl/etl-test.el +90 -0
  41. data/tracks/elisp/exercises/etl/etl.el +9 -0
  42. data/tracks/elisp/exercises/etl/example.el +22 -0
  43. data/tracks/elisp/exercises/nucleotide-count/example.el +19 -0
  44. data/tracks/elisp/exercises/nucleotide-count/nucleotide-count-test.el +34 -0
  45. data/tracks/elisp/exercises/nucleotide-count/nucleotide-count.el +9 -0
  46. data/tracks/elisp/exercises/perfect-numbers/example.el +28 -0
  47. data/tracks/elisp/exercises/perfect-numbers/perfect-numbers-test.el +24 -0
  48. data/tracks/elisp/exercises/perfect-numbers/perfect-numbers.el +10 -0
  49. data/tracks/elisp/exercises/roman-numerals/example.el +36 -0
  50. data/tracks/elisp/exercises/roman-numerals/roman-numerals-test.el +30 -0
  51. data/tracks/elisp/exercises/roman-numerals/roman-numerals.el +10 -0
  52. data/tracks/elisp/exercises/word-count/example.el +18 -0
  53. data/tracks/elisp/exercises/word-count/word-count-test.el +64 -0
  54. data/tracks/elisp/exercises/word-count/word-count.el +9 -0
  55. data/tracks/elixir/README.md +4 -4
  56. data/tracks/elixir/SETUP.md +3 -3
  57. data/tracks/elixir/docs/TESTS.md +3 -3
  58. data/tracks/elixir/exercises/accumulate/accumulate_test.exs +7 -7
  59. data/tracks/elixir/exercises/acronym/acronym_test.exs +5 -5
  60. data/tracks/elixir/exercises/allergies/allergies_test.exs +13 -13
  61. data/tracks/elixir/exercises/anagram/anagram_test.exs +12 -12
  62. data/tracks/elixir/exercises/atbash-cipher/atbash_cipher_test.exs +9 -9
  63. data/tracks/elixir/exercises/bank-account/bank_account_test.exs +5 -5
  64. data/tracks/elixir/exercises/beer-song/beer_song_test.exs +6 -6
  65. data/tracks/elixir/exercises/binary-search/binary_search_test.exs +7 -7
  66. data/tracks/elixir/exercises/binary/binary_test.exs +13 -13
  67. data/tracks/elixir/exercises/bob/bob_test.exs +15 -15
  68. data/tracks/elixir/exercises/bowling/bowling_test.exs +18 -18
  69. data/tracks/elixir/exercises/bracket-push/bracket_push_test.exs +12 -12
  70. data/tracks/elixir/exercises/change/change_test.exs +7 -7
  71. data/tracks/elixir/exercises/connect/connect_test.exs +9 -9
  72. data/tracks/elixir/exercises/crypto-square/crypto_square_test.exs +7 -7
  73. data/tracks/elixir/exercises/custom-set/custom_set_test.exs +11 -11
  74. data/tracks/elixir/exercises/diamond/diamond_test.exs +4 -4
  75. data/tracks/elixir/exercises/difference-of-squares/difference_of_squares_test.exs +10 -10
  76. data/tracks/elixir/exercises/dot-dsl/dot_dsl_test.exs +17 -17
  77. data/tracks/elixir/exercises/etl/etl_test.exs +5 -5
  78. data/tracks/elixir/exercises/flatten-array/flatten_array_test.exs +6 -6
  79. data/tracks/elixir/exercises/forth/forth_test.exs +16 -16
  80. data/tracks/elixir/exercises/gigasecond/gigasecond_test.exs +5 -5
  81. data/tracks/elixir/exercises/grade-school/grade_school_test.exs +6 -6
  82. data/tracks/elixir/exercises/grains/grains_test.exs +9 -9
  83. data/tracks/elixir/exercises/hamming/hamming_test.exs +6 -6
  84. data/tracks/elixir/exercises/hello-world/hello_world_test.exs +3 -3
  85. data/tracks/elixir/exercises/hexadecimal/hexadecimal_test.exs +11 -11
  86. data/tracks/elixir/exercises/isogram/isogram_test.exs +10 -10
  87. data/tracks/elixir/exercises/kindergarten-garden/garden_test.exs +7 -7
  88. data/tracks/elixir/exercises/largest-series-product/largest_series_product_test.exs +17 -17
  89. data/tracks/elixir/exercises/leap/leap_test.exs +5 -5
  90. data/tracks/elixir/exercises/list-ops/list_ops_test.exs +26 -26
  91. data/tracks/elixir/exercises/luhn/luhn_test.exs +7 -7
  92. data/tracks/elixir/exercises/markdown/markdown_test.exs +10 -10
  93. data/tracks/elixir/exercises/meetup/meetup_test.exs +92 -92
  94. data/tracks/elixir/exercises/minesweeper/minesweeper_test.exs +8 -8
  95. data/tracks/elixir/exercises/nth-prime/nth_prime_test.exs +6 -6
  96. data/tracks/elixir/exercises/nucleotide-count/example.exs +0 -5
  97. data/tracks/elixir/exercises/nucleotide-count/nucleotide_count_test.exs +7 -7
  98. data/tracks/elixir/exercises/palindrome-products/palindrome_products_test.exs +6 -6
  99. data/tracks/elixir/exercises/pangram/pangram_test.exs +11 -11
  100. data/tracks/elixir/exercises/parallel-letter-frequency/parallel_letter_frequency_test.exs +10 -10
  101. data/tracks/elixir/exercises/pascals-triangle/pascals_triangle_test.exs +7 -7
  102. data/tracks/elixir/exercises/phone-number/phone_number_test.exs +10 -10
  103. data/tracks/elixir/exercises/prime-factors/prime_factors_test.exs +13 -13
  104. data/tracks/elixir/exercises/pythagorean-triplet/pythagorean_triplet_test.exs +8 -8
  105. data/tracks/elixir/exercises/queen-attack/queen_attack_test.exs +16 -16
  106. data/tracks/elixir/exercises/rail-fence-cipher/rail_fence_cipher_test.exs +13 -13
  107. data/tracks/elixir/exercises/raindrops/raindrops_test.exs +17 -17
  108. data/tracks/elixir/exercises/rna-transcription/rna_transcription_test.exs +6 -6
  109. data/tracks/elixir/exercises/robot-simulator/robot_simulator_test.exs +6 -6
  110. data/tracks/elixir/exercises/roman-numerals/roman_numerals_test.exs +19 -19
  111. data/tracks/elixir/exercises/run-length-encoding/rle_test.exs +6 -6
  112. data/tracks/elixir/exercises/saddle-points/saddle_points_test.exs +11 -11
  113. data/tracks/elixir/exercises/scrabble-score/scrabble_score_test.exs +9 -9
  114. data/tracks/elixir/exercises/sieve/sieve_test.exs +3 -3
  115. data/tracks/elixir/exercises/space-age/space_age_test.exs +9 -9
  116. data/tracks/elixir/exercises/sublist/sublist_test.exs +20 -20
  117. data/tracks/elixir/exercises/sum-of-multiples/sum_of_multiples_test.exs +11 -11
  118. data/tracks/elixir/exercises/test_helper.exs +1 -1
  119. data/tracks/elixir/exercises/triangle/triangle_test.exs +16 -16
  120. data/tracks/elixir/exercises/word-count/word_count_test.exs +9 -9
  121. data/tracks/elixir/exercises/wordy/wordy_test.exs +16 -16
  122. data/tracks/elixir/exercises/zipper/zipper_test.exs +13 -13
  123. data/tracks/fsharp/build.fsx +2 -7
  124. data/tracks/fsharp/config.json +0 -104
  125. data/tracks/fsharp/exercises/grep/GrepTest.fs +7 -1
  126. data/tracks/go/config.json +1 -0
  127. data/tracks/go/exercises/acronym/acronym_test.go +36 -0
  128. data/tracks/go/exercises/acronym/example.go +21 -0
  129. data/tracks/go/exercises/palindrome-products/example.go +2 -0
  130. data/tracks/go/exercises/palindrome-products/palindrome_products_test.go +10 -0
  131. data/tracks/go/exercises/phone-number/example.go +2 -0
  132. data/tracks/go/exercises/phone-number/phone_number_test.go +44 -27
  133. data/tracks/go/exercises/robot-simulator/defs.go +6 -6
  134. data/tracks/go/exercises/robot-simulator/example.go +22 -22
  135. data/tracks/go/exercises/robot-simulator/robot_simulator_step2_test.go +28 -28
  136. data/tracks/go/exercises/robot-simulator/robot_simulator_step3_test.go +75 -76
  137. data/tracks/go/exercises/robot-simulator/robot_simulator_test.go +10 -4
  138. data/tracks/haskell/exercises/anagram/HINTS.md +22 -0
  139. data/tracks/haskell/exercises/anagram/package.yaml +3 -0
  140. data/tracks/haskell/exercises/anagram/src/Example.hs +10 -7
  141. data/tracks/haskell/exercises/anagram/test/Tests.hs +9 -3
  142. data/tracks/haskell/exercises/beer-song/HINTS.md +18 -0
  143. data/tracks/haskell/exercises/beer-song/src/Beer.hs +301 -3
  144. data/tracks/haskell/exercises/beer-song/src/Example.hs +5 -3
  145. data/tracks/haskell/exercises/beer-song/test/Tests.hs +332 -23
  146. data/tracks/haskell/exercises/crypto-square/src/CryptoSquare.hs +3 -17
  147. data/tracks/haskell/exercises/crypto-square/src/Example.hs +12 -20
  148. data/tracks/haskell/exercises/crypto-square/test/Tests.hs +46 -86
  149. data/tracks/haskell/exercises/leap/HINTS.md +11 -0
  150. data/tracks/haskell/exercises/leap/src/LeapYear.hs +1 -0
  151. data/tracks/java/exercises/pangram/src/test/java/PangramTest.java +34 -4
  152. data/tracks/lua/exercises/pov/pov_spec.lua +0 -13
  153. data/tracks/mips/docs/ABOUT.md +1 -1
  154. data/tracks/objective-c/config.json +225 -0
  155. data/tracks/objective-c/exercises/largest-series-product/LargestSeriesProductExample.h +8 -0
  156. data/tracks/objective-c/exercises/largest-series-product/LargestSeriesProductExample.m +63 -0
  157. data/tracks/objective-c/exercises/largest-series-product/LargestSeriesProductTest.m +84 -0
  158. data/tracks/objective-c/xcodeProject/ObjectiveC.xcodeproj/project.pbxproj +18 -0
  159. data/tracks/ocaml/.travis-ci.sh +23 -0
  160. data/tracks/ocaml/.travis.yml +5 -1
  161. data/tracks/ocaml/Makefile +41 -0
  162. data/tracks/ocaml/config.json +18 -0
  163. data/tracks/ocaml/exercises/anagram/Makefile +1 -0
  164. data/tracks/ocaml/exercises/beer-song/Makefile +1 -0
  165. data/tracks/ocaml/exercises/beer-song/{beer.mli → beer_song.mli} +0 -0
  166. data/tracks/ocaml/exercises/beer-song/example.ml +1 -1
  167. data/tracks/ocaml/exercises/beer-song/test.ml +7 -6
  168. data/tracks/ocaml/exercises/bob/Makefile +1 -0
  169. data/tracks/ocaml/exercises/bowling/Makefile +1 -0
  170. data/tracks/ocaml/exercises/custom-set/Makefile +1 -0
  171. data/tracks/ocaml/exercises/difference-of-squares/.merlin +5 -0
  172. data/tracks/ocaml/exercises/difference-of-squares/Makefile +11 -0
  173. data/tracks/ocaml/exercises/difference-of-squares/difference_of_squares.mli +8 -0
  174. data/tracks/ocaml/exercises/difference-of-squares/example.ml +21 -0
  175. data/tracks/ocaml/exercises/difference-of-squares/test.ml +32 -0
  176. data/tracks/ocaml/exercises/grade-school/Makefile +1 -0
  177. data/tracks/ocaml/exercises/grade-school/{school.mli → grade_school.mli} +0 -0
  178. data/tracks/ocaml/exercises/grade-school/test.ml +27 -27
  179. data/tracks/ocaml/exercises/hamming/Makefile +1 -0
  180. data/tracks/ocaml/exercises/hangman/Makefile +1 -0
  181. data/tracks/ocaml/exercises/hello-world/Makefile +1 -1
  182. data/tracks/ocaml/exercises/hello-world/{hello.ml → hello_world.ml} +0 -0
  183. data/tracks/ocaml/exercises/hello-world/{hello.mli → hello_world.mli} +0 -0
  184. data/tracks/ocaml/exercises/hello-world/test.ml +1 -1
  185. data/tracks/ocaml/exercises/hexadecimal/Makefile +1 -0
  186. data/tracks/ocaml/exercises/leap/Makefile +1 -1
  187. data/tracks/ocaml/exercises/list-ops/Makefile +1 -0
  188. data/tracks/ocaml/exercises/luhn/Makefile +1 -0
  189. data/tracks/ocaml/exercises/minesweeper/Makefile +1 -0
  190. data/tracks/ocaml/exercises/nucleotide-count/Makefile +1 -0
  191. data/tracks/ocaml/exercises/nucleotide-count/{dna.mli → nucleotide_count.mli} +0 -0
  192. data/tracks/ocaml/exercises/nucleotide-count/test.ml +7 -7
  193. data/tracks/ocaml/exercises/phone-number/Makefile +1 -0
  194. data/tracks/ocaml/exercises/phone-number/{phone.mli → phone_number.mli} +0 -0
  195. data/tracks/ocaml/exercises/phone-number/test.ml +10 -10
  196. data/tracks/ocaml/exercises/point-mutations/Makefile +8 -0
  197. data/tracks/ocaml/exercises/point-mutations/example.ml +0 -0
  198. data/tracks/ocaml/exercises/prime-factors/Makefile +1 -0
  199. data/tracks/ocaml/exercises/raindrops/.merlin +5 -0
  200. data/tracks/ocaml/exercises/raindrops/Makefile +11 -0
  201. data/tracks/ocaml/exercises/raindrops/example.ml +11 -0
  202. data/tracks/ocaml/exercises/raindrops/raindrops.mli +7 -0
  203. data/tracks/ocaml/exercises/raindrops/test.ml +48 -0
  204. data/tracks/ocaml/exercises/rna-transcription/Makefile +1 -0
  205. data/tracks/ocaml/exercises/rna-transcription/{dna.mli → rna_transcription.mli} +0 -0
  206. data/tracks/ocaml/exercises/rna-transcription/test.ml +6 -6
  207. data/tracks/ocaml/exercises/roman-numerals/Makefile +1 -0
  208. data/tracks/ocaml/exercises/say/.gitignore +1 -0
  209. data/tracks/ocaml/exercises/say/.merlin +5 -0
  210. data/tracks/ocaml/exercises/say/Makefile +11 -0
  211. data/tracks/ocaml/exercises/say/example.ml +52 -0
  212. data/tracks/ocaml/exercises/say/say.mli +8 -0
  213. data/tracks/ocaml/exercises/say/test.ml +65 -0
  214. data/tracks/ocaml/exercises/space-age/Makefile +1 -0
  215. data/tracks/ocaml/exercises/word-count/Makefile +1 -0
  216. data/tracks/ocaml/exercises/word-count/example.ml +1 -1
  217. data/tracks/ocaml/exercises/zipper/HINT.md +5 -6
  218. data/tracks/ocaml/exercises/zipper/Makefile +1 -0
  219. data/tracks/ocaml/exercises/zipper/example.ml +2 -2
  220. data/tracks/ocaml/exercises/zipper/tree.ml +1 -1
  221. data/tracks/php/config.json +7 -1
  222. data/tracks/php/exercises/variable-length-quantity/example.php +56 -0
  223. data/tracks/php/exercises/variable-length-quantity/variable-length-quantity_test.php +149 -0
  224. data/tracks/python/config.json +1 -1
  225. data/tracks/ruby/.rubocop.yml +1915 -26
  226. data/tracks/ruby/bin/generate-acronym +7 -0
  227. data/tracks/ruby/bin/generate-nth-prime +7 -0
  228. data/tracks/ruby/config.json +482 -0
  229. data/tracks/ruby/exercises/acronym/.version +1 -0
  230. data/tracks/ruby/exercises/acronym/acronym_test.rb +45 -21
  231. data/tracks/ruby/exercises/acronym/example.rb +1 -1
  232. data/tracks/ruby/exercises/acronym/example.tt +19 -0
  233. data/tracks/ruby/exercises/anagram/anagram_test.rb +1 -1
  234. data/tracks/ruby/exercises/nth-prime/.version +1 -0
  235. data/tracks/ruby/exercises/nth-prime/example.rb +4 -0
  236. data/tracks/ruby/exercises/nth-prime/example.tt +23 -0
  237. data/tracks/ruby/exercises/nth-prime/nth_prime_test.rb +33 -10
  238. data/tracks/ruby/exercises/raindrops/.version +1 -1
  239. data/tracks/ruby/exercises/raindrops/example.rb +1 -1
  240. data/tracks/ruby/exercises/raindrops/raindrops_test.rb +20 -5
  241. data/tracks/ruby/lib/acronym_cases.rb +19 -0
  242. data/tracks/ruby/lib/generator.rb +3 -2
  243. data/tracks/ruby/lib/nth_prime_cases.rb +23 -0
  244. data/tracks/ruby/lib/raindrop_cases.rb +1 -1
  245. data/tracks/rust/README.md +1 -1
  246. data/tracks/scala/exercises/leap/src/test/scala/leap_test.scala +10 -0
  247. data/tracks/scala/exercises/prime-factors/example.scala +2 -5
  248. data/tracks/scala/exercises/prime-factors/src/test/scala/primefactors_test.scala +11 -13
  249. data/tracks/scheme/{anagram → exercises/anagram}/anagram-test.scm +0 -0
  250. data/tracks/scheme/{anagram → exercises/anagram}/anagram.scm +0 -0
  251. data/tracks/scheme/{anagram → exercises/anagram}/example.scm +0 -0
  252. data/tracks/scheme/{bob → exercises/bob}/bob-test.scm +0 -0
  253. data/tracks/scheme/{bob → exercises/bob}/bob.scm +0 -0
  254. data/tracks/scheme/{bob → exercises/bob}/example.scm +0 -0
  255. data/tracks/scheme/{difference-of-squares → exercises/difference-of-squares}/difference-of-squares-test.scm +0 -0
  256. data/tracks/scheme/{difference-of-squares → exercises/difference-of-squares}/example.scm +0 -0
  257. data/tracks/scheme/{difference-of-squares → exercises/difference-of-squares}/squares.scm +0 -0
  258. data/tracks/scheme/{grains → exercises/grains}/example.scm +0 -0
  259. data/tracks/scheme/{grains → exercises/grains}/grains-test.scm +0 -0
  260. data/tracks/scheme/{grains → exercises/grains}/grains.scm +0 -0
  261. data/tracks/scheme/{hamming → exercises/hamming}/example.scm +0 -0
  262. data/tracks/scheme/{hamming → exercises/hamming}/hamming-test.scm +0 -0
  263. data/tracks/scheme/{hamming → exercises/hamming}/hamming.scm +0 -0
  264. data/tracks/scheme/{hello-world → exercises/hello-world}/example.scm +0 -0
  265. data/tracks/scheme/{hello-world → exercises/hello-world}/hello-world-test.scm +0 -0
  266. data/tracks/scheme/{hello-world → exercises/hello-world}/hello-world.scm +0 -0
  267. data/tracks/scheme/{leap → exercises/leap}/example.scm +0 -0
  268. data/tracks/scheme/{leap → exercises/leap}/leap-test.scm +0 -0
  269. data/tracks/scheme/{leap → exercises/leap}/leap-year.scm +0 -0
  270. data/tracks/scheme/{list-ops → exercises/list-ops}/example.scm +0 -0
  271. data/tracks/scheme/{list-ops → exercises/list-ops}/list-ops-test.scm +0 -0
  272. data/tracks/scheme/{list-ops → exercises/list-ops}/list-ops.scm +0 -0
  273. data/tracks/scheme/{nucleotide-count → exercises/nucleotide-count}/example.scm +0 -0
  274. data/tracks/scheme/{nucleotide-count → exercises/nucleotide-count}/nucleotide-count-test.scm +0 -0
  275. data/tracks/scheme/{nucleotide-count → exercises/nucleotide-count}/nucleotide-count.scm +0 -0
  276. data/tracks/scheme/{phone-number → exercises/phone-number}/example.scm +0 -0
  277. data/tracks/scheme/{phone-number → exercises/phone-number}/phone-number-test.scm +0 -0
  278. data/tracks/scheme/{phone-number → exercises/phone-number}/phone-number.scm +0 -0
  279. data/tracks/scheme/{raindrops → exercises/raindrops}/example.scm +0 -0
  280. data/tracks/scheme/{raindrops → exercises/raindrops}/raindrops-test.scm +0 -0
  281. data/tracks/scheme/{raindrops → exercises/raindrops}/raindrops.scm +0 -0
  282. data/tracks/scheme/{rna-transcription → exercises/rna-transcription}/dna.scm +0 -0
  283. data/tracks/scheme/{rna-transcription → exercises/rna-transcription}/example.scm +0 -0
  284. data/tracks/scheme/{rna-transcription → exercises/rna-transcription}/rna-transcription-test.scm +0 -0
  285. data/tracks/scheme/{robot-name → exercises/robot-name}/example.scm +0 -0
  286. data/tracks/scheme/{robot-name → exercises/robot-name}/robot-name-test.scm +0 -0
  287. data/tracks/scheme/{robot-name → exercises/robot-name}/robot.scm +0 -0
  288. metadata +125 -64
@@ -1,31 +1,340 @@
1
- {-# OPTIONS_GHC -fno-warn-type-defaults #-}
2
-
3
- import Test.Hspec (Spec, describe, it, shouldBe)
1
+ import Control.Monad (unless)
2
+ import Test.Hspec (Spec, describe, expectationFailure, it, shouldBe)
4
3
  import Test.Hspec.Runner (configFastFail, defaultConfig, hspecWith)
5
4
 
6
- import Beer (sing, verse)
5
+ import Beer (song)
7
6
 
8
7
  main :: IO ()
9
8
  main = hspecWith defaultConfig {configFastFail = True} specs
10
9
 
11
10
  specs :: Spec
12
- specs = describe "beer-song" $ do
13
-
14
- -- As of 2016-07-30, there was no reference file
15
- -- for the test cases in `exercism/x-common`.
16
-
17
- describe "verse" $ do
18
- it "verse 8" $ verse 8 `shouldBe` verse_8
19
- it "verse 2" $ verse 2 `shouldBe` verse_2
20
- it "verse 1" $ verse 1 `shouldBe` verse_1
21
- it "verse 0" $ verse 0 `shouldBe` verse_0
22
- describe "sing" $ do
23
- it "song 8 6" $ sing 8 6 `shouldBe` song_8_6
24
- it "song 3 0" $ sing 3 0 `shouldBe` song_3_0
11
+
12
+ specs = describe "beer-song" $
13
+
14
+ describe "song" $ do
15
+
16
+ -- First we test the input, line by line, to give more
17
+ -- useful error messages.
18
+
19
+ it "matches lines" $ sequence_ lineAssertions
20
+
21
+ -- Finally, because testing lines we are unable
22
+ -- to detect a missing newline at the end of the
23
+ -- lyrics, we test the full song.
24
+
25
+ it "matches full song" $ song `shouldBe` lyrics
25
26
  where
26
- verse_8 = "8 bottles of beer on the wall, 8 bottles of beer.\nTake one down and pass it around, 7 bottles of beer on the wall.\n"
27
- verse_2 = "2 bottles of beer on the wall, 2 bottles of beer.\nTake one down and pass it around, 1 bottle of beer on the wall.\n"
28
- verse_1 = "1 bottle of beer on the wall, 1 bottle of beer.\nTake it down and pass it around, no more bottles of beer on the wall.\n"
29
- verse_0 = "No more bottles of beer on the wall, no more bottles of beer.\nGo to the store and buy some more, 99 bottles of beer on the wall.\n"
30
- song_8_6 = "8 bottles of beer on the wall, 8 bottles of beer.\nTake one down and pass it around, 7 bottles of beer on the wall.\n\n7 bottles of beer on the wall, 7 bottles of beer.\nTake one down and pass it around, 6 bottles of beer on the wall.\n\n6 bottles of beer on the wall, 6 bottles of beer.\nTake one down and pass it around, 5 bottles of beer on the wall.\n\n"
31
- song_3_0 = "3 bottles of beer on the wall, 3 bottles of beer.\nTake one down and pass it around, 2 bottles of beer on the wall.\n\n2 bottles of beer on the wall, 2 bottles of beer.\nTake one down and pass it around, 1 bottle of beer on the wall.\n\n1 bottle of beer on the wall, 1 bottle of beer.\nTake it down and pass it around, no more bottles of beer on the wall.\n\nNo more bottles of beer on the wall, no more bottles of beer.\nGo to the store and buy some more, 99 bottles of beer on the wall.\n\n"
27
+
28
+ lineAssertions = zipWith checkLine [1 :: Int ..] $ zipMaybe (lines song) (lines lyrics)
29
+
30
+ checkLine lineno (got, want) =
31
+ unless (got == want) $
32
+ expectationFailure $ "mismatch at line " ++ show lineno ++ "\nexpected: " ++ show want ++ "\n but got: " ++ show got
33
+
34
+ zipMaybe [] [] = []
35
+ zipMaybe (x:xs) [] = (Just x , Nothing) : zipMaybe xs []
36
+ zipMaybe [] (y:ys) = (Nothing, Just y ) : zipMaybe [] ys
37
+ zipMaybe (x:xs) (y:ys) = (Just x , Just y ) : zipMaybe xs ys
38
+
39
+ -- Lyrics extracted from `exercism/x-common` on 2016-10-03.
40
+
41
+ lyrics :: String
42
+ lyrics = "99 bottles of beer on the wall, 99 bottles of beer.\n\
43
+ \Take one down and pass it around, 98 bottles of beer on the wall.\n\
44
+ \\n\
45
+ \98 bottles of beer on the wall, 98 bottles of beer.\n\
46
+ \Take one down and pass it around, 97 bottles of beer on the wall.\n\
47
+ \\n\
48
+ \97 bottles of beer on the wall, 97 bottles of beer.\n\
49
+ \Take one down and pass it around, 96 bottles of beer on the wall.\n\
50
+ \\n\
51
+ \96 bottles of beer on the wall, 96 bottles of beer.\n\
52
+ \Take one down and pass it around, 95 bottles of beer on the wall.\n\
53
+ \\n\
54
+ \95 bottles of beer on the wall, 95 bottles of beer.\n\
55
+ \Take one down and pass it around, 94 bottles of beer on the wall.\n\
56
+ \\n\
57
+ \94 bottles of beer on the wall, 94 bottles of beer.\n\
58
+ \Take one down and pass it around, 93 bottles of beer on the wall.\n\
59
+ \\n\
60
+ \93 bottles of beer on the wall, 93 bottles of beer.\n\
61
+ \Take one down and pass it around, 92 bottles of beer on the wall.\n\
62
+ \\n\
63
+ \92 bottles of beer on the wall, 92 bottles of beer.\n\
64
+ \Take one down and pass it around, 91 bottles of beer on the wall.\n\
65
+ \\n\
66
+ \91 bottles of beer on the wall, 91 bottles of beer.\n\
67
+ \Take one down and pass it around, 90 bottles of beer on the wall.\n\
68
+ \\n\
69
+ \90 bottles of beer on the wall, 90 bottles of beer.\n\
70
+ \Take one down and pass it around, 89 bottles of beer on the wall.\n\
71
+ \\n\
72
+ \89 bottles of beer on the wall, 89 bottles of beer.\n\
73
+ \Take one down and pass it around, 88 bottles of beer on the wall.\n\
74
+ \\n\
75
+ \88 bottles of beer on the wall, 88 bottles of beer.\n\
76
+ \Take one down and pass it around, 87 bottles of beer on the wall.\n\
77
+ \\n\
78
+ \87 bottles of beer on the wall, 87 bottles of beer.\n\
79
+ \Take one down and pass it around, 86 bottles of beer on the wall.\n\
80
+ \\n\
81
+ \86 bottles of beer on the wall, 86 bottles of beer.\n\
82
+ \Take one down and pass it around, 85 bottles of beer on the wall.\n\
83
+ \\n\
84
+ \85 bottles of beer on the wall, 85 bottles of beer.\n\
85
+ \Take one down and pass it around, 84 bottles of beer on the wall.\n\
86
+ \\n\
87
+ \84 bottles of beer on the wall, 84 bottles of beer.\n\
88
+ \Take one down and pass it around, 83 bottles of beer on the wall.\n\
89
+ \\n\
90
+ \83 bottles of beer on the wall, 83 bottles of beer.\n\
91
+ \Take one down and pass it around, 82 bottles of beer on the wall.\n\
92
+ \\n\
93
+ \82 bottles of beer on the wall, 82 bottles of beer.\n\
94
+ \Take one down and pass it around, 81 bottles of beer on the wall.\n\
95
+ \\n\
96
+ \81 bottles of beer on the wall, 81 bottles of beer.\n\
97
+ \Take one down and pass it around, 80 bottles of beer on the wall.\n\
98
+ \\n\
99
+ \80 bottles of beer on the wall, 80 bottles of beer.\n\
100
+ \Take one down and pass it around, 79 bottles of beer on the wall.\n\
101
+ \\n\
102
+ \79 bottles of beer on the wall, 79 bottles of beer.\n\
103
+ \Take one down and pass it around, 78 bottles of beer on the wall.\n\
104
+ \\n\
105
+ \78 bottles of beer on the wall, 78 bottles of beer.\n\
106
+ \Take one down and pass it around, 77 bottles of beer on the wall.\n\
107
+ \\n\
108
+ \77 bottles of beer on the wall, 77 bottles of beer.\n\
109
+ \Take one down and pass it around, 76 bottles of beer on the wall.\n\
110
+ \\n\
111
+ \76 bottles of beer on the wall, 76 bottles of beer.\n\
112
+ \Take one down and pass it around, 75 bottles of beer on the wall.\n\
113
+ \\n\
114
+ \75 bottles of beer on the wall, 75 bottles of beer.\n\
115
+ \Take one down and pass it around, 74 bottles of beer on the wall.\n\
116
+ \\n\
117
+ \74 bottles of beer on the wall, 74 bottles of beer.\n\
118
+ \Take one down and pass it around, 73 bottles of beer on the wall.\n\
119
+ \\n\
120
+ \73 bottles of beer on the wall, 73 bottles of beer.\n\
121
+ \Take one down and pass it around, 72 bottles of beer on the wall.\n\
122
+ \\n\
123
+ \72 bottles of beer on the wall, 72 bottles of beer.\n\
124
+ \Take one down and pass it around, 71 bottles of beer on the wall.\n\
125
+ \\n\
126
+ \71 bottles of beer on the wall, 71 bottles of beer.\n\
127
+ \Take one down and pass it around, 70 bottles of beer on the wall.\n\
128
+ \\n\
129
+ \70 bottles of beer on the wall, 70 bottles of beer.\n\
130
+ \Take one down and pass it around, 69 bottles of beer on the wall.\n\
131
+ \\n\
132
+ \69 bottles of beer on the wall, 69 bottles of beer.\n\
133
+ \Take one down and pass it around, 68 bottles of beer on the wall.\n\
134
+ \\n\
135
+ \68 bottles of beer on the wall, 68 bottles of beer.\n\
136
+ \Take one down and pass it around, 67 bottles of beer on the wall.\n\
137
+ \\n\
138
+ \67 bottles of beer on the wall, 67 bottles of beer.\n\
139
+ \Take one down and pass it around, 66 bottles of beer on the wall.\n\
140
+ \\n\
141
+ \66 bottles of beer on the wall, 66 bottles of beer.\n\
142
+ \Take one down and pass it around, 65 bottles of beer on the wall.\n\
143
+ \\n\
144
+ \65 bottles of beer on the wall, 65 bottles of beer.\n\
145
+ \Take one down and pass it around, 64 bottles of beer on the wall.\n\
146
+ \\n\
147
+ \64 bottles of beer on the wall, 64 bottles of beer.\n\
148
+ \Take one down and pass it around, 63 bottles of beer on the wall.\n\
149
+ \\n\
150
+ \63 bottles of beer on the wall, 63 bottles of beer.\n\
151
+ \Take one down and pass it around, 62 bottles of beer on the wall.\n\
152
+ \\n\
153
+ \62 bottles of beer on the wall, 62 bottles of beer.\n\
154
+ \Take one down and pass it around, 61 bottles of beer on the wall.\n\
155
+ \\n\
156
+ \61 bottles of beer on the wall, 61 bottles of beer.\n\
157
+ \Take one down and pass it around, 60 bottles of beer on the wall.\n\
158
+ \\n\
159
+ \60 bottles of beer on the wall, 60 bottles of beer.\n\
160
+ \Take one down and pass it around, 59 bottles of beer on the wall.\n\
161
+ \\n\
162
+ \59 bottles of beer on the wall, 59 bottles of beer.\n\
163
+ \Take one down and pass it around, 58 bottles of beer on the wall.\n\
164
+ \\n\
165
+ \58 bottles of beer on the wall, 58 bottles of beer.\n\
166
+ \Take one down and pass it around, 57 bottles of beer on the wall.\n\
167
+ \\n\
168
+ \57 bottles of beer on the wall, 57 bottles of beer.\n\
169
+ \Take one down and pass it around, 56 bottles of beer on the wall.\n\
170
+ \\n\
171
+ \56 bottles of beer on the wall, 56 bottles of beer.\n\
172
+ \Take one down and pass it around, 55 bottles of beer on the wall.\n\
173
+ \\n\
174
+ \55 bottles of beer on the wall, 55 bottles of beer.\n\
175
+ \Take one down and pass it around, 54 bottles of beer on the wall.\n\
176
+ \\n\
177
+ \54 bottles of beer on the wall, 54 bottles of beer.\n\
178
+ \Take one down and pass it around, 53 bottles of beer on the wall.\n\
179
+ \\n\
180
+ \53 bottles of beer on the wall, 53 bottles of beer.\n\
181
+ \Take one down and pass it around, 52 bottles of beer on the wall.\n\
182
+ \\n\
183
+ \52 bottles of beer on the wall, 52 bottles of beer.\n\
184
+ \Take one down and pass it around, 51 bottles of beer on the wall.\n\
185
+ \\n\
186
+ \51 bottles of beer on the wall, 51 bottles of beer.\n\
187
+ \Take one down and pass it around, 50 bottles of beer on the wall.\n\
188
+ \\n\
189
+ \50 bottles of beer on the wall, 50 bottles of beer.\n\
190
+ \Take one down and pass it around, 49 bottles of beer on the wall.\n\
191
+ \\n\
192
+ \49 bottles of beer on the wall, 49 bottles of beer.\n\
193
+ \Take one down and pass it around, 48 bottles of beer on the wall.\n\
194
+ \\n\
195
+ \48 bottles of beer on the wall, 48 bottles of beer.\n\
196
+ \Take one down and pass it around, 47 bottles of beer on the wall.\n\
197
+ \\n\
198
+ \47 bottles of beer on the wall, 47 bottles of beer.\n\
199
+ \Take one down and pass it around, 46 bottles of beer on the wall.\n\
200
+ \\n\
201
+ \46 bottles of beer on the wall, 46 bottles of beer.\n\
202
+ \Take one down and pass it around, 45 bottles of beer on the wall.\n\
203
+ \\n\
204
+ \45 bottles of beer on the wall, 45 bottles of beer.\n\
205
+ \Take one down and pass it around, 44 bottles of beer on the wall.\n\
206
+ \\n\
207
+ \44 bottles of beer on the wall, 44 bottles of beer.\n\
208
+ \Take one down and pass it around, 43 bottles of beer on the wall.\n\
209
+ \\n\
210
+ \43 bottles of beer on the wall, 43 bottles of beer.\n\
211
+ \Take one down and pass it around, 42 bottles of beer on the wall.\n\
212
+ \\n\
213
+ \42 bottles of beer on the wall, 42 bottles of beer.\n\
214
+ \Take one down and pass it around, 41 bottles of beer on the wall.\n\
215
+ \\n\
216
+ \41 bottles of beer on the wall, 41 bottles of beer.\n\
217
+ \Take one down and pass it around, 40 bottles of beer on the wall.\n\
218
+ \\n\
219
+ \40 bottles of beer on the wall, 40 bottles of beer.\n\
220
+ \Take one down and pass it around, 39 bottles of beer on the wall.\n\
221
+ \\n\
222
+ \39 bottles of beer on the wall, 39 bottles of beer.\n\
223
+ \Take one down and pass it around, 38 bottles of beer on the wall.\n\
224
+ \\n\
225
+ \38 bottles of beer on the wall, 38 bottles of beer.\n\
226
+ \Take one down and pass it around, 37 bottles of beer on the wall.\n\
227
+ \\n\
228
+ \37 bottles of beer on the wall, 37 bottles of beer.\n\
229
+ \Take one down and pass it around, 36 bottles of beer on the wall.\n\
230
+ \\n\
231
+ \36 bottles of beer on the wall, 36 bottles of beer.\n\
232
+ \Take one down and pass it around, 35 bottles of beer on the wall.\n\
233
+ \\n\
234
+ \35 bottles of beer on the wall, 35 bottles of beer.\n\
235
+ \Take one down and pass it around, 34 bottles of beer on the wall.\n\
236
+ \\n\
237
+ \34 bottles of beer on the wall, 34 bottles of beer.\n\
238
+ \Take one down and pass it around, 33 bottles of beer on the wall.\n\
239
+ \\n\
240
+ \33 bottles of beer on the wall, 33 bottles of beer.\n\
241
+ \Take one down and pass it around, 32 bottles of beer on the wall.\n\
242
+ \\n\
243
+ \32 bottles of beer on the wall, 32 bottles of beer.\n\
244
+ \Take one down and pass it around, 31 bottles of beer on the wall.\n\
245
+ \\n\
246
+ \31 bottles of beer on the wall, 31 bottles of beer.\n\
247
+ \Take one down and pass it around, 30 bottles of beer on the wall.\n\
248
+ \\n\
249
+ \30 bottles of beer on the wall, 30 bottles of beer.\n\
250
+ \Take one down and pass it around, 29 bottles of beer on the wall.\n\
251
+ \\n\
252
+ \29 bottles of beer on the wall, 29 bottles of beer.\n\
253
+ \Take one down and pass it around, 28 bottles of beer on the wall.\n\
254
+ \\n\
255
+ \28 bottles of beer on the wall, 28 bottles of beer.\n\
256
+ \Take one down and pass it around, 27 bottles of beer on the wall.\n\
257
+ \\n\
258
+ \27 bottles of beer on the wall, 27 bottles of beer.\n\
259
+ \Take one down and pass it around, 26 bottles of beer on the wall.\n\
260
+ \\n\
261
+ \26 bottles of beer on the wall, 26 bottles of beer.\n\
262
+ \Take one down and pass it around, 25 bottles of beer on the wall.\n\
263
+ \\n\
264
+ \25 bottles of beer on the wall, 25 bottles of beer.\n\
265
+ \Take one down and pass it around, 24 bottles of beer on the wall.\n\
266
+ \\n\
267
+ \24 bottles of beer on the wall, 24 bottles of beer.\n\
268
+ \Take one down and pass it around, 23 bottles of beer on the wall.\n\
269
+ \\n\
270
+ \23 bottles of beer on the wall, 23 bottles of beer.\n\
271
+ \Take one down and pass it around, 22 bottles of beer on the wall.\n\
272
+ \\n\
273
+ \22 bottles of beer on the wall, 22 bottles of beer.\n\
274
+ \Take one down and pass it around, 21 bottles of beer on the wall.\n\
275
+ \\n\
276
+ \21 bottles of beer on the wall, 21 bottles of beer.\n\
277
+ \Take one down and pass it around, 20 bottles of beer on the wall.\n\
278
+ \\n\
279
+ \20 bottles of beer on the wall, 20 bottles of beer.\n\
280
+ \Take one down and pass it around, 19 bottles of beer on the wall.\n\
281
+ \\n\
282
+ \19 bottles of beer on the wall, 19 bottles of beer.\n\
283
+ \Take one down and pass it around, 18 bottles of beer on the wall.\n\
284
+ \\n\
285
+ \18 bottles of beer on the wall, 18 bottles of beer.\n\
286
+ \Take one down and pass it around, 17 bottles of beer on the wall.\n\
287
+ \\n\
288
+ \17 bottles of beer on the wall, 17 bottles of beer.\n\
289
+ \Take one down and pass it around, 16 bottles of beer on the wall.\n\
290
+ \\n\
291
+ \16 bottles of beer on the wall, 16 bottles of beer.\n\
292
+ \Take one down and pass it around, 15 bottles of beer on the wall.\n\
293
+ \\n\
294
+ \15 bottles of beer on the wall, 15 bottles of beer.\n\
295
+ \Take one down and pass it around, 14 bottles of beer on the wall.\n\
296
+ \\n\
297
+ \14 bottles of beer on the wall, 14 bottles of beer.\n\
298
+ \Take one down and pass it around, 13 bottles of beer on the wall.\n\
299
+ \\n\
300
+ \13 bottles of beer on the wall, 13 bottles of beer.\n\
301
+ \Take one down and pass it around, 12 bottles of beer on the wall.\n\
302
+ \\n\
303
+ \12 bottles of beer on the wall, 12 bottles of beer.\n\
304
+ \Take one down and pass it around, 11 bottles of beer on the wall.\n\
305
+ \\n\
306
+ \11 bottles of beer on the wall, 11 bottles of beer.\n\
307
+ \Take one down and pass it around, 10 bottles of beer on the wall.\n\
308
+ \\n\
309
+ \10 bottles of beer on the wall, 10 bottles of beer.\n\
310
+ \Take one down and pass it around, 9 bottles of beer on the wall.\n\
311
+ \\n\
312
+ \9 bottles of beer on the wall, 9 bottles of beer.\n\
313
+ \Take one down and pass it around, 8 bottles of beer on the wall.\n\
314
+ \\n\
315
+ \8 bottles of beer on the wall, 8 bottles of beer.\n\
316
+ \Take one down and pass it around, 7 bottles of beer on the wall.\n\
317
+ \\n\
318
+ \7 bottles of beer on the wall, 7 bottles of beer.\n\
319
+ \Take one down and pass it around, 6 bottles of beer on the wall.\n\
320
+ \\n\
321
+ \6 bottles of beer on the wall, 6 bottles of beer.\n\
322
+ \Take one down and pass it around, 5 bottles of beer on the wall.\n\
323
+ \\n\
324
+ \5 bottles of beer on the wall, 5 bottles of beer.\n\
325
+ \Take one down and pass it around, 4 bottles of beer on the wall.\n\
326
+ \\n\
327
+ \4 bottles of beer on the wall, 4 bottles of beer.\n\
328
+ \Take one down and pass it around, 3 bottles of beer on the wall.\n\
329
+ \\n\
330
+ \3 bottles of beer on the wall, 3 bottles of beer.\n\
331
+ \Take one down and pass it around, 2 bottles of beer on the wall.\n\
332
+ \\n\
333
+ \2 bottles of beer on the wall, 2 bottles of beer.\n\
334
+ \Take one down and pass it around, 1 bottle of beer on the wall.\n\
335
+ \\n\
336
+ \1 bottle of beer on the wall, 1 bottle of beer.\n\
337
+ \Take it down and pass it around, no more bottles of beer on the wall.\n\
338
+ \\n\
339
+ \No more bottles of beer on the wall, no more bottles of beer.\n\
340
+ \Go to the store and buy some more, 99 bottles of beer on the wall.\n"
@@ -1,18 +1,4 @@
1
- module CryptoSquare
2
- ( ciphertext
3
- , normalizeCiphertext
4
- , normalizePlaintext
5
- , plaintextSegments
6
- ) where
1
+ module CryptoSquare (encode) where
7
2
 
8
- ciphertext :: String -> String
9
- ciphertext = undefined
10
-
11
- normalizeCiphertext :: String -> String
12
- normalizeCiphertext = undefined
13
-
14
- normalizePlaintext :: String -> String
15
- normalizePlaintext = undefined
16
-
17
- plaintextSegments :: String -> [String]
18
- plaintextSegments = undefined
3
+ encode :: String -> String
4
+ encode = undefined
@@ -1,23 +1,15 @@
1
- module CryptoSquare ( normalizePlaintext
2
- , plaintextSegments
3
- , ciphertext
4
- , normalizeCiphertext ) where
1
+ module CryptoSquare (encode) where
5
2
 
6
- import Data.Char (isAlphaNum, toLower)
7
- import Data.List (transpose)
3
+ import Data.Char (isAlphaNum, toLower)
4
+ import Data.List (transpose)
8
5
  import Data.List.Split (chunksOf)
9
6
 
10
- squareSize :: String -> Int
11
- squareSize = ceiling . (sqrt :: Double -> Double) . fromIntegral . length
12
-
13
- normalizePlaintext :: String -> String
14
- normalizePlaintext = map toLower . filter isAlphaNum
15
-
16
- plaintextSegments :: String -> [String]
17
- plaintextSegments = (squareSize >>= chunksOf) . normalizePlaintext
18
-
19
- ciphertext :: String -> String
20
- ciphertext = concat . transpose . plaintextSegments
21
-
22
- normalizeCiphertext :: String -> String
23
- normalizeCiphertext = unwords . transpose . plaintextSegments
7
+ encode :: String -> String
8
+ encode = unwords
9
+ . transpose
10
+ . (squareSize >>= chunksOf)
11
+ . map toLower
12
+ . filter isAlphaNum
13
+ where
14
+ squareSize :: String -> Int
15
+ squareSize = ceiling . (sqrt :: Double -> Double) . fromIntegral . length
@@ -1,93 +1,53 @@
1
- import Test.Hspec (Spec, describe, it, shouldBe)
1
+ {-# LANGUAGE RecordWildCards #-}
2
+
3
+ import Data.Char (isSpace)
4
+ import Data.Foldable (for_)
5
+ import Data.Function (on)
6
+ import Test.Hspec (Spec, describe, it, shouldBe, shouldMatchList)
2
7
  import Test.Hspec.Runner (configFastFail, defaultConfig, hspecWith)
3
8
 
4
- import CryptoSquare
5
- ( ciphertext
6
- , normalizeCiphertext
7
- , normalizePlaintext
8
- , plaintextSegments
9
- )
9
+ import CryptoSquare (encode)
10
10
 
11
11
  main :: IO ()
12
12
  main = hspecWith defaultConfig {configFastFail = True} specs
13
13
 
14
14
  specs :: Spec
15
- specs = describe "crypto-square" $ do
16
-
17
- -- Test cases adapted from `exercism/x-common/crypto-square.json`
18
- -- on 2016-08-02. Some deviations exist and are noted in comments.
19
-
20
- describe "normalizePlaintext" $ do
21
-
22
- it "Lowercase" $
23
- normalizePlaintext "Hello"
24
- `shouldBe` "hello"
25
-
26
- it "Remove spaces" $
27
- normalizePlaintext "Hi there"
28
- `shouldBe` "hithere"
29
-
30
- it "Remove punctuation" $
31
- normalizePlaintext "@1, 2%, 3 Go!"
32
- `shouldBe` "123go"
33
-
34
- describe "plaintextSegments" $ do
35
-
36
- it "empty plaintext results in an empty rectangle" $
37
- plaintextSegments ""
38
- `shouldBe` []
39
-
40
- it "4 character plaintext results in an 2x2 rectangle" $
41
- plaintextSegments "Ab Cd"
42
- `shouldBe` [ "ab"
43
- , "cd" ]
44
-
45
- it "9 character plaintext results in an 3x3 rectangle" $
46
- plaintextSegments "This is fun!"
47
- `shouldBe` [ "thi"
48
- , "sis"
49
- , "fun" ]
50
-
51
- it "54 character plaintext results in an 8x7 rectangle" $
52
- plaintextSegments "If man was meant to stay on the ground, god would have given us roots."
53
- `shouldBe` [ "ifmanwas"
54
- , "meanttos"
55
- , "tayonthe"
56
- , "groundgo"
57
- , "dwouldha"
58
- , "vegivenu"
59
- , "sroots" ]
60
-
61
- describe "ciphertext" $ do
62
-
63
- -- The function described by the reference file in `x-common`
64
- -- as `encoded` is called `ciphertext` in this track.
65
-
66
- it "empty plaintext results in an empty encode" $
67
- ciphertext ""
68
- `shouldBe` ""
69
-
70
- it "Non-empty plaintext results in the combined plaintext segments" $
71
- ciphertext "If man was meant to stay on the ground, god would have given us roots."
72
- `shouldBe` "imtgdvsfearwermayoogoanouuiontnnlvtwttddesaohghnsseoau"
73
-
74
- describe "normalizeCiphertext" $ do
75
-
76
- -- The function described by the reference file in `x-common`
77
- -- as `ciphertext` is called `normalizeCiphertext` in this track.
78
-
79
- it "empty plaintext results in an empty ciphertext" $
80
- normalizeCiphertext ""
81
- `shouldBe` ""
82
-
83
- it "9 character plaintext results in 3 chunks of 3 characters" $
84
- normalizeCiphertext "This is fun!"
85
- `shouldBe` "tsf hiu isn"
86
-
87
- {- In this track the encoded text chunks are not padded with spaces.
88
-
89
- it "54 character plaintext results in 7 chunks, the last two padded with spaces" $
90
- normalizeCiphertext "If man was meant to stay on the ground, god would have given us roots."
91
- `shouldBe` "imtgdvs fearwer mayoogo anouuio ntnnlvt wttddes aohghn sseoau "
92
-
93
- -}
15
+ specs = describe "crypto-square" $
16
+ describe "encode" $ for_ cases test
17
+ where
18
+
19
+ test Case{..} = describe description $ do
20
+
21
+ let shouldMatchWords = shouldBe `on` words
22
+ shouldMatchString = shouldBe `on` filter (not . isSpace)
23
+ shouldMatchChars = shouldMatchList `on` filter (not . isSpace)
24
+
25
+ it "normalizes the input" $ encode input `shouldMatchChars` expected
26
+ it "reorders the characters" $ encode input `shouldMatchString` expected
27
+ it "groups the output" $ encode input `shouldMatchWords` expected
28
+
29
+ -- Test cases created from scratch on 2016-10-05, diverging from `x-common`.
30
+
31
+ data Case = Case { description :: String
32
+ , input :: String
33
+ , expected :: String
34
+ }
35
+
36
+ cases :: [Case]
37
+ cases = [ Case { description = "perfect square, all lowercase with space"
38
+ , input = "a dog"
39
+ , expected = "ao dg"
40
+ }
41
+ , Case { description = "perfect rectangle, mixed case"
42
+ , input = "A camel"
43
+ , expected = "am ce al"
44
+ }
45
+ , Case { description = "incomplete square with punctuation"
46
+ , input = "Wait, fox!"
47
+ , expected = "wtx af io"
48
+ }
49
+ , Case { description = "incomplete rectangle with symbols"
50
+ , input = "cat | cut -d@ -f1 | sort | uniq"
51
+ , expected = "ctoi adrq tft c1u usn"
52
+ }
53
+ ]