trackler 2.2.1.99 → 2.2.1.100

Sign up to get free protection for your applications and to get access to all the features.
Files changed (296) hide show
  1. checksums.yaml +4 -4
  2. data/lib/trackler/version.rb +1 -1
  3. data/problem-specifications/exercises/clock/canonical-data.json +303 -204
  4. data/problem-specifications/exercises/complex-numbers/canonical-data.json +104 -44
  5. data/problem-specifications/exercises/matrix/canonical-data.json +78 -0
  6. data/problem-specifications/exercises/word-count/canonical-data.json +12 -12
  7. data/tracks/bash/config.json +128 -110
  8. data/tracks/c/exercises/word-count/test/test_word_count.c +2 -2
  9. data/tracks/dart/CONTRIBUTING.md +2 -2
  10. data/tracks/dart/docs/EXERCISE_README_INSERT.md +0 -1
  11. data/tracks/dart/docs/INSTALLATION.md +17 -11
  12. data/tracks/fsharp/exercises/acronym/AcronymTest.fs +3 -7
  13. data/tracks/fsharp/exercises/anagram/AnagramTest.fs +1 -21
  14. data/tracks/fsharp/exercises/book-store/BookStoreTest.fs +1 -1
  15. data/tracks/fsharp/exercises/complex-numbers/ComplexNumbersTest.fs +25 -25
  16. data/tracks/fsharp/exercises/custom-set/CustomSetTest.fs +1 -1
  17. data/tracks/fsharp/exercises/food-chain/FoodChainTest.fs +1 -1
  18. data/tracks/fsharp/exercises/gigasecond/GigasecondTest.fs +1 -1
  19. data/tracks/fsharp/exercises/hamming/HammingTest.fs +1 -1
  20. data/tracks/fsharp/exercises/hello-world/HelloWorldTest.fs +1 -1
  21. data/tracks/fsharp/exercises/largest-series-product/LargestSeriesProductTest.fs +1 -1
  22. data/tracks/fsharp/exercises/leap/LeapTest.fs +1 -1
  23. data/tracks/fsharp/exercises/markdown/MarkdownTest.fs +19 -19
  24. data/tracks/fsharp/exercises/minesweeper/MinesweeperTest.fs +27 -27
  25. data/tracks/fsharp/exercises/nth-prime/NthPrimeTest.fs +1 -1
  26. data/tracks/fsharp/exercises/nucleotide-count/NucleotideCountTest.fs +1 -1
  27. data/tracks/fsharp/exercises/pangram/PangramTest.fs +1 -1
  28. data/tracks/fsharp/exercises/pascals-triangle/PascalsTriangleTest.fs +1 -1
  29. data/tracks/fsharp/exercises/perfect-numbers/PerfectNumbersTest.fs +1 -1
  30. data/tracks/fsharp/exercises/phone-number/PhoneNumberTest.fs +11 -3
  31. data/tracks/fsharp/exercises/pig-latin/PigLatinTest.fs +1 -1
  32. data/tracks/fsharp/exercises/protein-translation/Example.fs +2 -2
  33. data/tracks/fsharp/exercises/protein-translation/ProteinTranslation.fs +1 -1
  34. data/tracks/fsharp/exercises/protein-translation/ProteinTranslationTest.fs +94 -60
  35. data/tracks/fsharp/exercises/react/ReactTest.fs +1 -1
  36. data/tracks/fsharp/exercises/rna-transcription/RnaTranscriptionTest.fs +1 -1
  37. data/tracks/fsharp/exercises/roman-numerals/RomanNumeralsTest.fs +1 -1
  38. data/tracks/fsharp/exercises/rotational-cipher/RotationalCipherTest.fs +1 -1
  39. data/tracks/fsharp/exercises/say/Example.fs +1 -1
  40. data/tracks/fsharp/exercises/say/SayTest.fs +21 -24
  41. data/tracks/fsharp/exercises/scrabble-score/ScrabbleScoreTest.fs +1 -1
  42. data/tracks/fsharp/exercises/secret-handshake/Example.fs +2 -2
  43. data/tracks/fsharp/exercises/secret-handshake/SecretHandshake.fs +1 -1
  44. data/tracks/fsharp/exercises/secret-handshake/SecretHandshakeTest.fs +39 -22
  45. data/tracks/fsharp/exercises/sieve/Example.fs +1 -1
  46. data/tracks/fsharp/exercises/sieve/Sieve.fs +1 -1
  47. data/tracks/fsharp/exercises/sieve/SieveTest.fs +19 -21
  48. data/tracks/fsharp/exercises/spiral-matrix/SpiralMatrixTest.fs +1 -1
  49. data/tracks/fsharp/exercises/sum-of-multiples/Example.fs +1 -1
  50. data/tracks/fsharp/exercises/sum-of-multiples/SumOfMultiples.fs +1 -1
  51. data/tracks/fsharp/exercises/sum-of-multiples/SumOfMultiplesTest.fs +44 -14
  52. data/tracks/fsharp/exercises/twelve-days/TwelveDaysTest.fs +1 -1
  53. data/tracks/fsharp/exercises/two-fer/Example.fs +1 -1
  54. data/tracks/fsharp/exercises/two-fer/TwoFer.fs +1 -1
  55. data/tracks/fsharp/exercises/two-fer/TwoFerTest.fs +4 -4
  56. data/tracks/fsharp/exercises/word-count/Example.fs +2 -2
  57. data/tracks/fsharp/exercises/word-count/WordCount.fs +2 -2
  58. data/tracks/fsharp/exercises/word-count/WordCountTest.fs +80 -100
  59. data/tracks/fsharp/exercises/wordy/Example.fs +2 -3
  60. data/tracks/fsharp/exercises/wordy/Wordy.fs +1 -1
  61. data/tracks/fsharp/exercises/wordy/WordyTest.fs +51 -49
  62. data/tracks/fsharp/exercises/zebra-puzzle/Example.fs +4 -4
  63. data/tracks/fsharp/exercises/zebra-puzzle/ZebraPuzzleTest.fs +7 -8
  64. data/tracks/fsharp/generators/Common.fs +3 -1
  65. data/tracks/fsharp/generators/Exercise.fs +12 -1
  66. data/tracks/fsharp/generators/Generators.fs +89 -42
  67. data/tracks/fsharp/generators/Generators.fsproj +1 -0
  68. data/tracks/fsharp/generators/Options.fs +14 -7
  69. data/tracks/fsharp/generators/Program.fs +3 -0
  70. data/tracks/fsharp/generators/Rendering.fs +0 -1
  71. data/tracks/fsharp/generators/Track.fs +26 -0
  72. data/tracks/go/exercises/custom-set/.meta/gen.go +16 -14
  73. data/tracks/go/exercises/custom-set/cases_test.go +2 -2
  74. data/tracks/java/exercises/food-chain/.meta/version +1 -0
  75. data/tracks/java/exercises/sieve/.meta/version +1 -0
  76. data/tracks/java/exercises/sieve/src/test/java/SieveTest.java +17 -0
  77. data/tracks/java/exercises/twelve-days/.meta/version +1 -0
  78. data/tracks/java/exercises/twelve-days/src/test/java/TwelveDaysTest.java +15 -3
  79. data/tracks/java/exercises/two-fer/.meta/version +1 -0
  80. data/tracks/java/exercises/two-fer/src/test/java/TwoferTest.java +0 -9
  81. data/tracks/ocaml/config/exercise_readme.go.tmpl +38 -4
  82. data/tracks/ocaml/exercises/acronym/README.md +0 -2
  83. data/tracks/ocaml/exercises/all-your-base/README.md +1 -3
  84. data/tracks/ocaml/exercises/anagram/README.md +0 -1
  85. data/tracks/ocaml/exercises/atbash-cipher/README.md +2 -2
  86. data/tracks/ocaml/exercises/beer-song/README.md +2 -3
  87. data/tracks/ocaml/exercises/binary-search/README.md +0 -1
  88. data/tracks/ocaml/exercises/bob/README.md +2 -1
  89. data/tracks/ocaml/exercises/bowling/README.md +20 -7
  90. data/tracks/ocaml/exercises/bracket-push/README.md +0 -1
  91. data/tracks/ocaml/exercises/change/README.md +1 -2
  92. data/tracks/ocaml/exercises/connect/README.md +1 -3
  93. data/tracks/ocaml/exercises/custom-set/README.md +0 -2
  94. data/tracks/ocaml/exercises/difference-of-squares/README.md +0 -1
  95. data/tracks/ocaml/exercises/dominoes/README.md +3 -5
  96. data/tracks/ocaml/exercises/etl/README.md +3 -2
  97. data/tracks/ocaml/exercises/forth/README.md +0 -2
  98. data/tracks/ocaml/exercises/grade-school/README.md +0 -1
  99. data/tracks/ocaml/exercises/hamming/README.md +0 -1
  100. data/tracks/ocaml/exercises/hangman/README.md +0 -2
  101. data/tracks/ocaml/exercises/hello-world/README.md +0 -1
  102. data/tracks/ocaml/exercises/hexadecimal/README.md +0 -1
  103. data/tracks/ocaml/exercises/leap/README.md +1 -2
  104. data/tracks/ocaml/exercises/list-ops/README.md +0 -2
  105. data/tracks/ocaml/exercises/luhn/README.md +7 -8
  106. data/tracks/ocaml/exercises/meetup/README.md +16 -14
  107. data/tracks/ocaml/exercises/minesweeper/README.md +0 -2
  108. data/tracks/ocaml/exercises/nucleotide-count/README.md +8 -23
  109. data/tracks/ocaml/exercises/palindrome-products/README.md +0 -1
  110. data/tracks/ocaml/exercises/pangram/README.md +1 -2
  111. data/tracks/ocaml/exercises/phone-number/README.md +4 -4
  112. data/tracks/ocaml/exercises/prime-factors/README.md +0 -1
  113. data/tracks/ocaml/exercises/raindrops/README.md +0 -1
  114. data/tracks/ocaml/exercises/react/README.md +0 -2
  115. data/tracks/ocaml/{docs/EXERCISE_README_INSERT.md → exercises/rectangles/README.md} +67 -0
  116. data/tracks/ocaml/exercises/rna-transcription/README.md +1 -2
  117. data/tracks/ocaml/exercises/robot-name/README.md +0 -1
  118. data/tracks/ocaml/exercises/roman-numerals/README.md +1 -2
  119. data/tracks/ocaml/exercises/run-length-encoding/README.md +4 -5
  120. data/tracks/ocaml/exercises/say/README.md +0 -1
  121. data/tracks/ocaml/exercises/space-age/README.md +1 -2
  122. data/tracks/ocaml/exercises/triangle/README.md +8 -6
  123. data/tracks/ocaml/exercises/word-count/README.md +1 -3
  124. data/tracks/ocaml/exercises/zipper/README.md +1 -3
  125. data/tracks/perl6/.travis.yml +1 -1
  126. data/tracks/perl6/bin/README.md +1 -2
  127. data/tracks/perl6/bin/exercise-gen.pl6 +18 -18
  128. data/tracks/perl6/config.json +1 -0
  129. data/tracks/perl6/exercises/accumulate/{example.yaml → .meta/exercise-data.yaml} +0 -0
  130. data/tracks/perl6/exercises/accumulate/{Example.pm6 → .meta/solutions/Accumulate.pm6} +0 -0
  131. data/tracks/perl6/exercises/acronym/{example.yaml → .meta/exercise-data.yaml} +0 -0
  132. data/tracks/perl6/exercises/acronym/{Example.pm6 → .meta/solutions/Acronym.pm6} +0 -0
  133. data/tracks/perl6/exercises/all-your-base/{example.yaml → .meta/exercise-data.yaml} +0 -0
  134. data/tracks/perl6/exercises/all-your-base/{Example.pm6 → .meta/solutions/AllYourBase.pm6} +0 -0
  135. data/tracks/perl6/exercises/allergies/{example.yaml → .meta/exercise-data.yaml} +0 -0
  136. data/tracks/perl6/exercises/allergies/{Example.pm6 → .meta/solutions/Allergies.pm6} +0 -0
  137. data/tracks/perl6/exercises/anagram/{example.yaml → .meta/exercise-data.yaml} +0 -0
  138. data/tracks/perl6/exercises/anagram/{Example.pm6 → .meta/solutions/Anagram.pm6} +0 -0
  139. data/tracks/perl6/exercises/atbash-cipher/{example.yaml → .meta/exercise-data.yaml} +0 -0
  140. data/tracks/perl6/exercises/atbash-cipher/{Example.pm6 → .meta/solutions/AtbashCipher.pm6} +0 -0
  141. data/tracks/perl6/exercises/binary/{Example.pm6 → .meta/solutions/Trinary.pm6} +0 -0
  142. data/tracks/perl6/exercises/bob/{example.yaml → .meta/exercise-data.yaml} +0 -0
  143. data/tracks/perl6/exercises/bob/{Example.pm6 → .meta/solutions/Bob.pm6} +0 -0
  144. data/tracks/perl6/exercises/clock/{example.yaml → .meta/exercise-data.yaml} +0 -0
  145. data/tracks/perl6/exercises/clock/{Example.pm6 → .meta/solutions/Clock.pm6} +0 -0
  146. data/tracks/perl6/exercises/etl/{example.yaml → .meta/exercise-data.yaml} +0 -0
  147. data/tracks/perl6/exercises/etl/{Example.pm6 → .meta/solutions/ETL.pm6} +0 -0
  148. data/tracks/perl6/exercises/flatten-array/{example.yaml → .meta/exercise-data.yaml} +0 -0
  149. data/tracks/perl6/exercises/flatten-array/{Example.pm6 → .meta/solutions/FlattenArray.pm6} +0 -0
  150. data/tracks/perl6/exercises/grade-school/{example.yaml → .meta/exercise-data.yaml} +0 -0
  151. data/tracks/perl6/exercises/grade-school/{Example.pm6 → .meta/solutions/GradeSchool.pm6} +0 -0
  152. data/tracks/perl6/exercises/grains/{example.yaml → .meta/exercise-data.yaml} +0 -0
  153. data/tracks/perl6/exercises/grains/{Example.pm6 → .meta/solutions/Grains.pm6} +0 -0
  154. data/tracks/perl6/exercises/hamming/{example.yaml → .meta/exercise-data.yaml} +0 -0
  155. data/tracks/perl6/exercises/hamming/{Example.pm6 → .meta/solutions/Hamming.pm6} +0 -0
  156. data/tracks/perl6/exercises/hello-world/{example.yaml → .meta/exercise-data.yaml} +0 -0
  157. data/tracks/perl6/exercises/hello-world/{Example.pm6 → .meta/solutions/HelloWorld.pm6} +0 -0
  158. data/tracks/perl6/exercises/leap/{example.yaml → .meta/exercise-data.yaml} +0 -0
  159. data/tracks/perl6/exercises/leap/{Example.pm6 → .meta/solutions/Leap.pm6} +0 -0
  160. data/tracks/perl6/exercises/linked-list/{example.yaml → .meta/exercise-data.yaml} +0 -0
  161. data/tracks/perl6/exercises/linked-list/{Example.pm6 → .meta/solutions/LinkedList.pm6} +0 -0
  162. data/tracks/perl6/exercises/luhn/{example.yaml → .meta/exercise-data.yaml} +0 -0
  163. data/tracks/perl6/exercises/luhn/{Example.pm6 → .meta/solutions/Luhn.pm6} +0 -0
  164. data/tracks/perl6/exercises/meetup/{example.yaml → .meta/exercise-data.yaml} +0 -0
  165. data/tracks/perl6/exercises/meetup/{Example.pm6 → .meta/solutions/Meetup.pm6} +0 -0
  166. data/tracks/perl6/exercises/nucleotide-count/{example.yaml → .meta/exercise-data.yaml} +0 -0
  167. data/tracks/perl6/exercises/nucleotide-count/{Example.pm6 → .meta/solutions/NucleotideCount.pm6} +0 -0
  168. data/tracks/perl6/exercises/pangram/{example.yaml → .meta/exercise-data.yaml} +0 -0
  169. data/tracks/perl6/exercises/pangram/{Example.pm6 → .meta/solutions/Pangram.pm6} +0 -0
  170. data/tracks/perl6/exercises/phone-number/{example.yaml → .meta/exercise-data.yaml} +0 -0
  171. data/tracks/perl6/exercises/phone-number/{Example.pm6 → .meta/solutions/Phone.pm6} +0 -0
  172. data/tracks/perl6/exercises/raindrops/{example.yaml → .meta/exercise-data.yaml} +0 -0
  173. data/tracks/perl6/exercises/raindrops/{Example.pm6 → .meta/solutions/Raindrops.pm6} +0 -0
  174. data/tracks/perl6/exercises/rna-transcription/{example.yaml → .meta/exercise-data.yaml} +0 -0
  175. data/tracks/perl6/exercises/rna-transcription/{Example.pm6 → .meta/solutions/RNA.pm6} +0 -0
  176. data/tracks/perl6/exercises/robot-name/{example.yaml → .meta/exercise-data.yaml} +0 -0
  177. data/tracks/perl6/exercises/robot-name/{Example.pm6 → .meta/solutions/Robot.pm6} +0 -0
  178. data/tracks/perl6/exercises/roman-numerals/{example.yaml → .meta/exercise-data.yaml} +0 -0
  179. data/tracks/perl6/exercises/roman-numerals/{Example.pm6 → .meta/solutions/RomanNumerals.pm6} +0 -0
  180. data/tracks/perl6/exercises/scrabble-score/{example.yaml → .meta/exercise-data.yaml} +0 -0
  181. data/tracks/perl6/exercises/scrabble-score/{Example.pm6 → .meta/solutions/Scrabble.pm6} +0 -0
  182. data/tracks/perl6/exercises/space-age/{example.yaml → .meta/exercise-data.yaml} +0 -0
  183. data/tracks/perl6/exercises/space-age/{Example.pm6 → .meta/solutions/SpaceAge.pm6} +0 -0
  184. data/tracks/perl6/exercises/trinary/{Example.pm6 → .meta/solutions/Trinary.pm6} +0 -0
  185. data/tracks/perl6/exercises/two-fer/{example.yaml → .meta/exercise-data.yaml} +0 -0
  186. data/tracks/perl6/exercises/two-fer/{Example.pm6 → .meta/solutions/TwoFer.pm6} +0 -0
  187. data/tracks/perl6/exercises/word-count/{example.yaml → .meta/exercise-data.yaml} +0 -0
  188. data/tracks/perl6/exercises/word-count/{Example.pm6 → .meta/solutions/WordCount.pm6} +0 -0
  189. data/tracks/perl6/exercises/wordy/{example.yaml → .meta/exercise-data.yaml} +0 -0
  190. data/tracks/perl6/exercises/wordy/{Example.pm6 → .meta/solutions/Wordy.pm6} +0 -0
  191. data/tracks/perl6/t/generated-tests.t +2 -2
  192. data/tracks/python/config.json +12 -0
  193. data/tracks/python/exercises/bowling/.gitignore +0 -0
  194. data/tracks/python/exercises/bowling/bowling.py +11 -0
  195. data/tracks/python/exercises/bowling/bowling_test.py +193 -0
  196. data/tracks/python/exercises/bowling/example.py +149 -0
  197. data/tracks/python/exercises/say/say_test.py +1 -1
  198. data/tracks/ruby/README.md +121 -97
  199. data/tracks/ruby/config/exercise_readme.go.tmpl +23 -4
  200. data/tracks/ruby/exercises/accumulate/{HINTS.md → .meta/hints.md} +0 -0
  201. data/tracks/ruby/exercises/accumulate/README.md +3 -5
  202. data/tracks/ruby/exercises/acronym/README.md +3 -6
  203. data/tracks/ruby/exercises/all-your-base/README.md +4 -7
  204. data/tracks/ruby/exercises/allergies/README.md +3 -6
  205. data/tracks/ruby/exercises/alphametics/README.md +5 -8
  206. data/tracks/ruby/exercises/anagram/README.md +3 -5
  207. data/tracks/ruby/exercises/atbash-cipher/README.md +5 -6
  208. data/tracks/ruby/exercises/beer-song/README.md +5 -7
  209. data/tracks/ruby/exercises/binary-search-tree/README.md +3 -5
  210. data/tracks/ruby/exercises/binary-search/README.md +3 -5
  211. data/tracks/ruby/exercises/binary/README.md +5 -5
  212. data/tracks/ruby/exercises/bob/README.md +3 -5
  213. data/tracks/ruby/exercises/book-store/README.md +3 -5
  214. data/tracks/ruby/exercises/bowling/README.md +23 -11
  215. data/tracks/ruby/exercises/bracket-push/README.md +3 -5
  216. data/tracks/ruby/exercises/change/README.md +3 -5
  217. data/tracks/ruby/exercises/circular-buffer/README.md +16 -11
  218. data/tracks/ruby/exercises/clock/README.md +3 -5
  219. data/tracks/ruby/exercises/collatz-conjecture/README.md +4 -6
  220. data/tracks/ruby/exercises/complex-numbers/README.md +6 -8
  221. data/tracks/ruby/exercises/connect/README.md +4 -7
  222. data/tracks/ruby/exercises/crypto-square/README.md +3 -5
  223. data/tracks/ruby/exercises/custom-set/README.md +3 -6
  224. data/tracks/ruby/exercises/diamond/README.md +9 -11
  225. data/tracks/ruby/exercises/difference-of-squares/README.md +3 -5
  226. data/tracks/ruby/exercises/dominoes/README.md +6 -9
  227. data/tracks/ruby/exercises/etl/README.md +6 -6
  228. data/tracks/ruby/exercises/flatten-array/README.md +5 -8
  229. data/tracks/ruby/exercises/food-chain/README.md +4 -6
  230. data/tracks/ruby/exercises/gigasecond/README.md +3 -5
  231. data/tracks/ruby/exercises/grade-school/README.md +3 -6
  232. data/tracks/ruby/exercises/grains/README.md +3 -6
  233. data/tracks/ruby/exercises/hamming/README.md +3 -5
  234. data/tracks/ruby/exercises/hello-world/README.md +1 -3
  235. data/tracks/ruby/exercises/hexadecimal/README.md +3 -5
  236. data/tracks/ruby/exercises/house/README.md +5 -8
  237. data/tracks/ruby/exercises/isbn-verifier/README.md +4 -6
  238. data/tracks/ruby/exercises/isogram/README.md +5 -6
  239. data/tracks/ruby/exercises/kindergarten-garden/README.md +16 -18
  240. data/tracks/ruby/exercises/largest-series-product/README.md +3 -5
  241. data/tracks/ruby/exercises/leap/README.md +4 -6
  242. data/tracks/ruby/exercises/linked-list/README.md +13 -15
  243. data/tracks/ruby/exercises/list-ops/README.md +3 -6
  244. data/tracks/ruby/exercises/luhn/README.md +10 -12
  245. data/tracks/ruby/exercises/matrix/README.md +9 -9
  246. data/tracks/ruby/exercises/meetup/README.md +19 -18
  247. data/tracks/ruby/exercises/minesweeper/README.md +3 -6
  248. data/tracks/ruby/exercises/nth-prime/README.md +3 -5
  249. data/tracks/ruby/exercises/nucleotide-count/README.md +11 -27
  250. data/tracks/ruby/exercises/ocr-numbers/README.md +9 -11
  251. data/tracks/ruby/exercises/octal/README.md +9 -7
  252. data/tracks/ruby/exercises/palindrome-products/README.md +8 -17
  253. data/tracks/ruby/exercises/pangram/README.md +4 -6
  254. data/tracks/ruby/exercises/pascals-triangle/README.md +5 -7
  255. data/tracks/ruby/exercises/perfect-numbers/README.md +5 -7
  256. data/tracks/ruby/exercises/phone-number/README.md +7 -8
  257. data/tracks/ruby/exercises/pig-latin/README.md +3 -5
  258. data/tracks/ruby/exercises/point-mutations/README.md +3 -5
  259. data/tracks/ruby/exercises/poker/README.md +3 -5
  260. data/tracks/ruby/exercises/prime-factors/README.md +3 -5
  261. data/tracks/ruby/exercises/protein-translation/README.md +7 -10
  262. data/tracks/ruby/exercises/proverb/README.md +17 -14
  263. data/tracks/ruby/exercises/pythagorean-triplet/README.md +6 -8
  264. data/tracks/ruby/exercises/queen-attack/README.md +4 -6
  265. data/tracks/ruby/exercises/rail-fence-cipher/README.md +15 -12
  266. data/tracks/ruby/exercises/raindrops/README.md +3 -5
  267. data/tracks/ruby/exercises/rna-transcription/README.md +4 -6
  268. data/tracks/ruby/exercises/robot-name/{HINTS.md → .meta/hints.md} +0 -0
  269. data/tracks/ruby/exercises/robot-name/README.md +3 -5
  270. data/tracks/ruby/exercises/robot-simulator/README.md +3 -5
  271. data/tracks/ruby/exercises/roman-numerals/README.md +4 -6
  272. data/tracks/ruby/exercises/rotational-cipher/README.md +3 -5
  273. data/tracks/ruby/exercises/run-length-encoding/README.md +7 -9
  274. data/tracks/ruby/exercises/saddle-points/README.md +5 -7
  275. data/tracks/ruby/exercises/say/README.md +3 -5
  276. data/tracks/ruby/exercises/scale-generator/README.md +3 -7
  277. data/tracks/ruby/exercises/scrabble-score/README.md +6 -6
  278. data/tracks/ruby/exercises/secret-handshake/README.md +4 -6
  279. data/tracks/ruby/exercises/series/README.md +3 -5
  280. data/tracks/ruby/exercises/sieve/README.md +3 -5
  281. data/tracks/ruby/exercises/simple-cipher/README.md +7 -11
  282. data/tracks/ruby/exercises/simple-linked-list/README.md +3 -5
  283. data/tracks/ruby/exercises/space-age/README.md +4 -6
  284. data/tracks/ruby/exercises/strain/README.md +3 -5
  285. data/tracks/ruby/exercises/sum-of-multiples/README.md +6 -11
  286. data/tracks/ruby/exercises/tournament/README.md +8 -11
  287. data/tracks/ruby/exercises/transpose/README.md +10 -12
  288. data/tracks/ruby/exercises/triangle/README.md +12 -11
  289. data/tracks/ruby/exercises/trinary/README.md +4 -6
  290. data/tracks/ruby/exercises/twelve-days/README.md +4 -6
  291. data/tracks/ruby/exercises/two-bucket/README.md +13 -15
  292. data/tracks/ruby/exercises/two-fer/README.md +13 -39
  293. data/tracks/ruby/exercises/word-count/README.md +4 -7
  294. data/tracks/ruby/exercises/wordy/README.md +3 -10
  295. metadata +77 -68
  296. data/tracks/ruby/docs/EXERCISE_README_INSERT.md +0 -24
@@ -1,3 +1,3 @@
1
1
  module Wordy
2
2
 
3
- let solve question = failwith "You need to implement this function."
3
+ let answer question = failwith "You need to implement this function."
@@ -1,71 +1,73 @@
1
- // This file was created manually and its version is 1.0.0.
1
+ // This file was auto-generated based on version 1.1.0 of the canonical data.
2
2
 
3
3
  module WordyTest
4
4
 
5
- open Xunit
6
5
  open FsUnit.Xunit
6
+ open Xunit
7
+
7
8
  open Wordy
8
9
 
9
10
  [<Fact>]
10
- let ``Can parse and solve addition problems`` () =
11
- solve "What is 1 plus 1?" |> should equal <| Some 2
12
-
11
+ let ``Addition`` () =
12
+ answer "What is 1 plus 1?" |> should equal (Some 2)
13
+
13
14
  [<Fact(Skip = "Remove to run test")>]
14
- let ``Can add double digit numbers`` () =
15
- solve "What is 53 plus 2?" |> should equal <| Some 55
16
-
15
+ let ``More addition`` () =
16
+ answer "What is 53 plus 2?" |> should equal (Some 55)
17
+
17
18
  [<Fact(Skip = "Remove to run test")>]
18
- let ``Can add negative numbers`` () =
19
- solve "What is -1 plus -10?" |> should equal <| Some -11
20
-
19
+ let ``Addition with negative numbers`` () =
20
+ answer "What is -1 plus -10?" |> should equal (Some -11)
21
+
21
22
  [<Fact(Skip = "Remove to run test")>]
22
- let ``Can add large numbers`` () =
23
- solve "What is 123 plus 45678?" |> should equal <| Some 45801
24
-
23
+ let ``Large addition`` () =
24
+ answer "What is 123 plus 45678?" |> should equal (Some 45801)
25
+
25
26
  [<Fact(Skip = "Remove to run test")>]
26
- let ``Can parse and solve subtraction problems`` () =
27
- solve "What is 4 minus -12?" |> should equal <| Some 16
28
-
27
+ let ``Subtraction`` () =
28
+ answer "What is 4 minus -12?" |> should equal (Some 16)
29
+
29
30
  [<Fact(Skip = "Remove to run test")>]
30
- let ``Can parse and solve multiplication problems`` () =
31
- solve "What is -3 multiplied by 25?" |> should equal <| Some -75
32
-
31
+ let ``Multiplication`` () =
32
+ answer "What is -3 multiplied by 25?" |> should equal (Some -75)
33
+
33
34
  [<Fact(Skip = "Remove to run test")>]
34
- let ``Can parse and solve division problems`` () =
35
- solve "What is 33 divided by -3?" |> should equal <| Some -11
36
-
35
+ let ``Division`` () =
36
+ answer "What is 33 divided by -3?" |> should equal (Some -11)
37
+
37
38
  [<Fact(Skip = "Remove to run test")>]
38
- let ``Can add twice`` () =
39
- solve "What is 1 plus 1 plus 1?" |> should equal <| Some 3
40
-
39
+ let ``Multiple additions`` () =
40
+ answer "What is 1 plus 1 plus 1?" |> should equal (Some 3)
41
+
41
42
  [<Fact(Skip = "Remove to run test")>]
42
- let ``Can add then subtract`` () =
43
- solve "What is 1 plus 5 minus -2?" |> should equal <| Some 8
44
-
43
+ let ``Addition and subtraction`` () =
44
+ answer "What is 1 plus 5 minus -2?" |> should equal (Some 8)
45
+
45
46
  [<Fact(Skip = "Remove to run test")>]
46
- let ``Can subtract twice`` () =
47
- solve "What is 20 minus 4 minus 13?" |> should equal <| Some 3
48
-
47
+ let ``Multiple subtraction`` () =
48
+ answer "What is 20 minus 4 minus 13?" |> should equal (Some 3)
49
+
49
50
  [<Fact(Skip = "Remove to run test")>]
50
- let ``Can subtract then add`` () =
51
- solve "What is 17 minus 6 plus 3?" |> should equal <| Some 14
52
-
51
+ let ``Subtraction then addition`` () =
52
+ answer "What is 17 minus 6 plus 3?" |> should equal (Some 14)
53
+
53
54
  [<Fact(Skip = "Remove to run test")>]
54
- let ``Can multiply twice`` () =
55
- solve "What is 2 multiplied by -2 multiplied by 3?" |> should equal <| Some -12
56
-
55
+ let ``Multiple multiplication`` () =
56
+ answer "What is 2 multiplied by -2 multiplied by 3?" |> should equal (Some -12)
57
+
57
58
  [<Fact(Skip = "Remove to run test")>]
58
- let ``Can add then multiply`` () =
59
- solve "What is -3 plus 7 multiplied by -2?" |> should equal <| Some -8
60
-
59
+ let ``Addition and multiplication`` () =
60
+ answer "What is -3 plus 7 multiplied by -2?" |> should equal (Some -8)
61
+
61
62
  [<Fact(Skip = "Remove to run test")>]
62
- let ``Can divide twice`` () =
63
- solve "What is -12 divided by 2 divided by -3?" |> should equal <| Some 2
64
-
63
+ let ``Multiple division`` () =
64
+ answer "What is -12 divided by 2 divided by -3?" |> should equal (Some 2)
65
+
65
66
  [<Fact(Skip = "Remove to run test")>]
66
- let ``Cubed is too advanced`` () =
67
- solve "What is 53 cubed?" |> should equal None
68
-
67
+ let ``Unknown operation`` () =
68
+ answer "What is 52 cubed?" |> should equal None
69
+
69
70
  [<Fact(Skip = "Remove to run test")>]
70
- let ``Irrelevant problems are not valid`` () =
71
- solve "Who is the president of the United States?" |> should equal None
71
+ let ``Non math question`` () =
72
+ answer "Who is the President of the United States?" |> should equal None
73
+
@@ -14,7 +14,7 @@ let rec insertions x = function
14
14
 
15
15
  let rec permutations = function
16
16
  | [] -> seq [ [] ]
17
- | x :: xs -> Seq.concat (Seq.map (insertions x) (permutations xs))
17
+ | x :: xs -> Seq.collect (insertions x) (permutations xs)
18
18
 
19
19
  let index value = List.findIndex ((=) value)
20
20
 
@@ -74,7 +74,7 @@ let solutions = seq {
74
74
  yield { colors = validColors; nationalities = validNationalities; pets = validPets; drinks = validDrinks; smokes = validSmokes }
75
75
  }
76
76
 
77
- let solve() = Seq.head solutions
77
+ let solution = Seq.head solutions
78
78
 
79
- let whoDrinksWater solution = List.item (index Water solution.drinks) solution.nationalities
80
- let whoOwnsZebra solution = List.item (index Zebra solution.pets) solution.nationalities
79
+ let drinksWater = List.item (index Water solution.drinks) solution.nationalities
80
+ let ownsZebra = List.item (index Zebra solution.pets) solution.nationalities
@@ -1,18 +1,17 @@
1
- // This file was created manually and its version is 1.0.0.
1
+ // This file was auto-generated based on version 1.1.0 of the canonical data.
2
2
 
3
3
  module ZebraPuzzleTest
4
4
 
5
- open Xunit
6
5
  open FsUnit.Xunit
6
+ open Xunit
7
7
 
8
8
  open ZebraPuzzle
9
9
 
10
10
  [<Fact>]
11
- let ``Who drinks water?`` () =
12
- let solution = solve()
13
- whoDrinksWater solution |> should equal Norwegian
11
+ let ``Resident who drinks water`` () =
12
+ drinksWater |> should equal Norwegian
14
13
 
15
14
  [<Fact(Skip = "Remove to run test")>]
16
- let ``Who owns the zebra?`` () =
17
- let solution = solve()
18
- whoOwnsZebra solution |> should equal Japanese
15
+ let ``Resident who owns zebra`` () =
16
+ ownsZebra |> should equal Japanese
17
+
@@ -43,7 +43,7 @@ let isInt64 (value: obj) =
43
43
  | _ -> false
44
44
 
45
45
  module Option =
46
- let ofNonNegativeInt (value: obj) =
46
+ let ofPositiveInt (value: obj) =
47
47
  match value with
48
48
  | :? int64 as i -> if i < 0L then None else Some value
49
49
  | :? int32 as i -> if i < 0 then None else Some value
@@ -89,6 +89,8 @@ module String =
89
89
  let replace (oldValue: string) (newValue: string) (str: string) =
90
90
  str.Replace(oldValue, newValue)
91
91
 
92
+ let toLower (str: string) = str.ToLowerInvariant()
93
+
92
94
  module Json =
93
95
  let rec parentsAndSelf (currentToken: JToken) =
94
96
  let rec helper acc (token: JToken) =
@@ -10,6 +10,7 @@ open Serilog
10
10
  open Formatting
11
11
  open Rendering
12
12
  open CanonicalData
13
+ open Track
13
14
 
14
15
  let private exerciseNameFromType (exerciseType: Type) = exerciseType.Name.Kebaberize()
15
16
 
@@ -295,12 +296,15 @@ type CustomExercise() =
295
296
  type MissingDataExercise = { Name: string }
296
297
 
297
298
  type UnimplementedExercise = { Name: string }
299
+
300
+ type DeprecatedExercise = { Name: string }
298
301
 
299
302
  type Exercise =
300
303
  | Generator of GeneratorExercise
301
304
  | Custom of CustomExercise
302
305
  | MissingData of MissingDataExercise
303
306
  | Unimplemented of UnimplementedExercise
307
+ | Deprecated of DeprecatedExercise
304
308
 
305
309
  let exerciseName exercise =
306
310
  match exercise with
@@ -308,6 +312,7 @@ let exerciseName exercise =
308
312
  | Custom custom -> custom.Name
309
313
  | Unimplemented unimplemented -> unimplemented.Name
310
314
  | MissingData missingData -> missingData.Name
315
+ | Deprecated deprecated -> deprecated.Name
311
316
 
312
317
  type ConfigExercise = { Slug: string }
313
318
 
@@ -356,13 +361,19 @@ let private tryFindCustomExercise exerciseName =
356
361
  |> Map.tryFind exerciseName
357
362
  |> Option.map Custom
358
363
 
364
+ let private tryFindDeprecatedExercise exerciseName =
365
+ match isDeprecated exerciseName with
366
+ | true -> Deprecated { Name = exerciseName } |> Some
367
+ | false -> None
368
+
359
369
  let private tryFindUnimplementedExercise options exerciseName =
360
370
  match hasCanonicalData options exerciseName with
361
371
  | true -> Unimplemented { Name = exerciseName } |> Some
362
372
  | false -> None
363
373
 
364
374
  let private createExercise options exerciseName =
365
- tryFindGeneratorExercise exerciseName
375
+ tryFindDeprecatedExercise exerciseName
376
+ |> Option.orElse (tryFindGeneratorExercise exerciseName)
366
377
  |> Option.orElse (tryFindCustomExercise exerciseName)
367
378
  |> Option.orElse (tryFindUnimplementedExercise options exerciseName)
368
379
  |> Option.orElse (MissingData { Name = exerciseName } |> Some)
@@ -98,8 +98,7 @@ type BeerSong() =
98
98
  override __.PropertiesWithIdentifier _ = ["expected"]
99
99
 
100
100
  override __.RenderExpected (_, _, value) =
101
- (value :?> JArray)
102
- |> normalizeJArray
101
+ value :?> JArray
103
102
  |> Seq.map formatValue
104
103
  |> formatMultiLineList
105
104
 
@@ -125,7 +124,7 @@ type Bob() =
125
124
  type BookStore() =
126
125
  inherit GeneratorExercise()
127
126
 
128
- let formatFloat (value:obj) = value :?> float |> sprintf "%.2f"
127
+ let formatFloat (value:obj) = value :?> int64 |> (fun x -> float x / 100.0) |> sprintf "%.2f"
129
128
 
130
129
  override __.RenderExpected (_, _, value) = formatFloat value
131
130
 
@@ -163,7 +162,7 @@ type Change() =
163
162
  inherit GeneratorExercise()
164
163
 
165
164
  override __.RenderExpected (_, _, value) =
166
- let convertToOption = if value :? JArray then Option.ofObj else Option.ofNonNegativeInt
165
+ let convertToOption = if value :? JArray then Option.ofObj else Option.ofPositiveInt
167
166
  value |> convertToOption |> formatValue
168
167
 
169
168
  override this.PropertiesWithIdentifier canonicalDataCase = this.Properties canonicalDataCase
@@ -343,11 +342,10 @@ type CustomSet() =
343
342
 
344
343
  override __.TestMethodBodyAssertTemplate _ = "AssertEqual"
345
344
 
346
- member __.RenderSet canonicalDataCase key =
347
- let value =
348
- (canonicalDataCase.Properties.[key] :?> JToken).ToObject<seq<string>>()
349
- |> formatList
350
- sprintf "CustomSet.fromList %s" value
345
+ member __.RenderSet (jToken: obj) =
346
+ (jToken :?> JToken).ToObject<seq<string>>()
347
+ |> formatList
348
+ |> sprintf "CustomSet.fromList %s"
351
349
 
352
350
  override this.RenderSut canonicalDataCase =
353
351
  match canonicalDataCase.Property with
@@ -365,15 +363,15 @@ type CustomSet() =
365
363
  let arrangeLines =
366
364
  match canonicalDataCase.Property with
367
365
  | "empty" ->
368
- let setValue = this.RenderSet canonicalDataCase "set"
366
+ let setValue = this.RenderSet canonicalDataCase.Input.["set"]
369
367
  [ sprintf "let %s = CustomSet.isEmpty (%s)" this.SutName setValue ]
370
368
  | "add" | "contains" ->
371
369
  let methodName =
372
370
  match canonicalDataCase.Property with
373
371
  | "add" -> "insert"
374
372
  | s -> s
375
- let setVar = sprintf "let setValue = %s" (this.RenderSet canonicalDataCase "set")
376
- let valueVar = sprintf "let element = %s" (formatValue canonicalDataCase.Properties.["element"])
373
+ let setVar = sprintf "let setValue = %s" (this.RenderSet canonicalDataCase.Input.["set"])
374
+ let valueVar = sprintf "let element = %s" (formatValue canonicalDataCase.Input.["element"])
377
375
  let resultVar = sprintf "let %s = CustomSet.%s element setValue" this.SutName methodName
378
376
  [ setVar; valueVar; resultVar ]
379
377
  | "intersection" | "difference" | "union" | "disjoint" | "subset" | "equal" ->
@@ -383,8 +381,8 @@ type CustomSet() =
383
381
  | "subset" -> "isSubsetOf"
384
382
  | "equal" -> "isEqualTo"
385
383
  | s -> s
386
- let firstSetVar = sprintf "let set1 = %s" (this.RenderSet canonicalDataCase "set1")
387
- let secondSetVar = sprintf "let set2 = %s" (this.RenderSet canonicalDataCase "set2")
384
+ let firstSetVar = sprintf "let set1 = %s" (this.RenderSet canonicalDataCase.Input.["set1"])
385
+ let secondSetVar = sprintf "let set2 = %s" (this.RenderSet canonicalDataCase.Input.["set2"])
388
386
  let resultVar = sprintf "let %s = CustomSet.%s set1 set2" this.SutName methodName
389
387
  [ firstSetVar; secondSetVar; resultVar ]
390
388
  | _ ->
@@ -392,7 +390,7 @@ type CustomSet() =
392
390
 
393
391
  match canonicalDataCase.Property with
394
392
  | "add" | "intersection" | "difference" | "union" ->
395
- let expectedSetVar = sprintf "let expectedSet = %s" (this.RenderSet canonicalDataCase "expected")
393
+ let expectedSetVar = sprintf "let expectedSet = %s" (this.RenderSet canonicalDataCase.Expected)
396
394
  let actualBoolVar = sprintf "let %sBool = CustomSet.isEqualTo %s expectedSet" this.SutName this.SutName
397
395
  arrangeLines @ [ expectedSetVar; actualBoolVar ]
398
396
  | _ -> arrangeLines
@@ -407,8 +405,8 @@ type Dominoes() =
407
405
  inherit GeneratorExercise()
408
406
 
409
407
  let formatAsTuple (value:obj) =
410
- let twoElementList = value :?> JArray |> normalizeJArray
411
- (twoElementList.Item 0, twoElementList.Item 1) |> string
408
+ let items = value :?> obj list
409
+ formatTuple (List.item 0 items, List.item 1 items)
412
410
 
413
411
  override __.RenderInput (_, _, value) =
414
412
  value :?> JArray
@@ -451,8 +449,7 @@ type FoodChain() =
451
449
  override __.PropertiesWithIdentifier _ = ["expected"]
452
450
 
453
451
  override __.RenderExpected (_, _, value) =
454
- (value :?> JArray)
455
- |> normalizeJArray
452
+ value :?> JArray
456
453
  |> Seq.map formatValue
457
454
  |> formatMultiLineList
458
455
 
@@ -478,10 +475,8 @@ type Gigasecond() =
478
475
 
479
476
  override __.RenderExpected (_, _, value) = value :?> DateTime |> formatDateTime |> parenthesize
480
477
 
481
- override __.RenderInput (canonicalDataCase, key, value) =
482
- match key with
483
- | "input" -> DateTime.Parse(string value, CultureInfo.InvariantCulture) |> formatDateTime |> parenthesize
484
- | _ -> base.RenderInput (canonicalDataCase, key, value)
478
+ override __.RenderInput (_, _, value) =
479
+ DateTime.Parse(string value, CultureInfo.InvariantCulture) |> formatDateTime |> parenthesize
485
480
 
486
481
  override __.AdditionalNamespaces = [typeof<DateTime>.Namespace]
487
482
 
@@ -503,8 +498,7 @@ type Grep() =
503
498
  override this.PropertiesWithIdentifier canonicalDataCase = this.Properties canonicalDataCase
504
499
 
505
500
  override __.RenderExpected (_, _, value) =
506
- (value :?> JArray)
507
- |> normalizeJArray
501
+ value :?> JArray
508
502
  |> Seq.map formatValue
509
503
  |> formatMultiLineListWithIndentation 3
510
504
 
@@ -546,8 +540,7 @@ type House() =
546
540
  override __.PropertiesWithIdentifier _ = ["expected"]
547
541
 
548
542
  override __.RenderExpected (_, _, value) =
549
- (value :?> JArray)
550
- |> normalizeJArray
543
+ value :?> JArray
551
544
  |> Seq.map formatValue
552
545
  |> formatMultiLineList
553
546
 
@@ -578,7 +571,7 @@ type LargestSeriesProduct() =
578
571
 
579
572
  override __.RenderExpected (_, _, value) =
580
573
  value
581
- |> Option.ofNonNegativeInt
574
+ |> Option.ofPositiveInt
582
575
  |> formatValue
583
576
  |> parenthesizeOption
584
577
 
@@ -643,7 +636,6 @@ type Minesweeper() =
643
636
 
644
637
  let renderValue (value: obj) =
645
638
  value :?> JArray
646
- |> normalizeJArray
647
639
  |> Seq.map formatValue
648
640
  |> formatMultiLineList
649
641
 
@@ -698,7 +690,7 @@ type OcrNumbers() =
698
690
 
699
691
  override __.RenderExpected (_, _, value) =
700
692
  value
701
- |> Option.ofNonNegativeInt
693
+ |> Option.ofPositiveInt
702
694
  |> formatValue
703
695
  |> parenthesizeOption
704
696
 
@@ -715,8 +707,8 @@ type PalindromeProducts() =
715
707
  inherit GeneratorExercise()
716
708
 
717
709
  let toFactors (value: obj) =
718
- let jArray = value :?> JArray
719
- let factors = jArray.ToObject<int list>()
710
+ let jArray = value :?> obj list
711
+ let factors = jArray |> List.map (string >> int)
720
712
  sprintf "(%A, %A)" factors.[0] factors.[1]
721
713
 
722
714
  let toPalindromeProducts (value: obj) =
@@ -749,9 +741,8 @@ type PascalsTriangle() =
749
741
  | :? JArray ->
750
742
  let formattedList =
751
743
  value :?> JArray
752
- |> normalizeJArray
753
744
  |> Seq.map formatValue
754
- |> formatMultiLineList
745
+ |> formatMultiLineList
755
746
 
756
747
  if (formattedList.Contains("\n")) then
757
748
  sprintf "%s\n%s" formattedList (indent 2 "|> Some")
@@ -804,14 +795,16 @@ type PrimeFactors() =
804
795
  override __.RenderInput (canonicalDataCase, key, value) =
805
796
  base.RenderInput (canonicalDataCase, key, value) |> sprintf "%sL"
806
797
 
798
+ type ProteinTranslation() =
799
+ inherit GeneratorExercise()
800
+
807
801
  type Proverb() =
808
802
  inherit GeneratorExercise()
809
803
 
810
804
  override __.PropertiesWithIdentifier _ = ["input"; "expected"]
811
805
 
812
806
  override __.RenderExpected (_, _, value) =
813
- (value :?> JArray)
814
- |> normalizeJArray
807
+ value :?> JArray
815
808
  |> Seq.map formatValue
816
809
  |> formatMultiLineList
817
810
 
@@ -857,7 +850,7 @@ type React() =
857
850
  member private __.RenderCells canonicalDataCase =
858
851
  let reactorVar = sprintf "let %s = new %s()" "reactor" "Reactor"
859
852
  let cellVars =
860
- canonicalDataCase.Properties.["cells"] :?> JArray
853
+ canonicalDataCase.Input.["cells"] :?> JArray
861
854
  |> Seq.map (fun (cellValue: JToken) ->
862
855
  let cell = cellValue :?> JObject
863
856
  let cellName = cell.["name"].ToObject<string>()
@@ -878,7 +871,7 @@ type React() =
878
871
  [ reactorVar ] @ cellVars
879
872
 
880
873
  member private __.RenderOperations canonicalDataCase =
881
- canonicalDataCase.Properties.["operations"] :?> JArray
874
+ canonicalDataCase.Input.["operations"] :?> JArray
882
875
  // we can generate more than 1 line per operation
883
876
  // so we need to flatten results here
884
877
  // collect does it automatically for us
@@ -1046,18 +1039,43 @@ type RunLengthEncoding() =
1046
1039
  type RomanNumerals() =
1047
1040
  inherit GeneratorExercise()
1048
1041
 
1042
+ type Say() =
1043
+ inherit GeneratorExercise()
1044
+
1045
+ override __.RenderExpected (_, _, value) =
1046
+ value
1047
+ |> Option.ofPositiveInt
1048
+ |> formatValue
1049
+ |> parenthesizeOption
1050
+
1051
+ override __.RenderInput (_, _, value) = sprintf "%sL" (string value)
1052
+
1049
1053
  type ScrabbleScore() =
1050
1054
  inherit GeneratorExercise()
1051
1055
 
1052
- type SpiralMatrix() =
1056
+ type Sieve() =
1053
1057
  inherit GeneratorExercise()
1054
1058
 
1055
1059
  override __.RenderExpected (_, _, value) =
1056
1060
  (value :?> JArray)
1057
1061
  |> normalizeJArray
1058
1062
  |> Seq.map formatValue
1063
+ |> formatList
1064
+
1065
+ type SecretHandshake() =
1066
+ inherit GeneratorExercise()
1067
+
1068
+ type SpiralMatrix() =
1069
+ inherit GeneratorExercise()
1070
+
1071
+ override __.RenderExpected (_, _, value) =
1072
+ value :?> JArray
1073
+ |> Seq.map formatValue
1059
1074
  |> formatMultiLineList
1060
1075
 
1076
+ type SumOfMultiples() =
1077
+ inherit GeneratorExercise()
1078
+
1061
1079
  type TwelveDays() =
1062
1080
  inherit GeneratorExercise()
1063
1081
 
@@ -1066,8 +1084,7 @@ type TwelveDays() =
1066
1084
  override __.PropertiesWithIdentifier _ = ["expected"]
1067
1085
 
1068
1086
  override __.RenderExpected (_, _, value) =
1069
- (value :?> JArray)
1070
- |> normalizeJArray
1087
+ value :?> JArray
1071
1088
  |> Seq.map formatValue
1072
1089
  |> formatMultiLineList
1073
1090
 
@@ -1075,4 +1092,34 @@ type TwoFer() =
1075
1092
  inherit GeneratorExercise()
1076
1093
 
1077
1094
  override __.RenderInput (_, _, value) =
1078
- value |> Option.ofObj |> formatValue |> parenthesizeOption
1095
+ value |> Option.ofObj |> formatValue |> parenthesizeOption
1096
+
1097
+ type WordCount() =
1098
+ inherit GeneratorExercise()
1099
+ member __.FormatMap<'TKey, 'TValue> (value: obj) =
1100
+ let input = value :?> JObject
1101
+ let dict = input.ToObject<Collections.Generic.Dictionary<'TKey, 'TValue>>();
1102
+ let formattedList =
1103
+ dict
1104
+ |> Seq.map (fun kv -> formatTuple (kv.Key, kv.Value))
1105
+ |> formatMultiLineList
1106
+
1107
+ if (formattedList.Contains("\n")) then
1108
+ sprintf "%s\n%s" formattedList (indent 2 "|> Map.ofList")
1109
+ else
1110
+ sprintf "%s |> Map.ofList" formattedList
1111
+
1112
+ override this.RenderExpected (_, _, value) = this.FormatMap<string, int> value
1113
+
1114
+ override __.PropertiesWithIdentifier _ = ["expected"]
1115
+
1116
+ type Wordy() =
1117
+ inherit GeneratorExercise()
1118
+
1119
+ override __.RenderExpected (_, _, value) =
1120
+ value |> Option.ofNonFalse |> formatValue |> parenthesizeOption
1121
+
1122
+ type ZebraPuzzle() =
1123
+ inherit GeneratorExercise()
1124
+
1125
+ override __.RenderExpected (_, _, value) = string value