trackler 2.2.0.4 → 2.2.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (486) hide show
  1. checksums.yaml +4 -4
  2. data/lib/trackler/version.rb +1 -1
  3. data/tracks/bash/config.json +10 -2
  4. data/tracks/bash/exercises/word-count/example.awk +12 -0
  5. data/tracks/bash/exercises/word-count/example.sh +21 -0
  6. data/tracks/c/config.json +0 -2
  7. data/tracks/ceylon/config.json +0 -2
  8. data/tracks/{erlang/exercises/all-your-base/.meta/readme.go.tmpl → clojure/config/exercise_readme.go.tmpl} +0 -1
  9. data/tracks/clojure/exercises/accumulate/README.md +35 -0
  10. data/tracks/clojure/exercises/acronym/README.md +15 -0
  11. data/tracks/clojure/exercises/all-your-base/README.md +35 -0
  12. data/tracks/clojure/exercises/allergies/README.md +37 -0
  13. data/tracks/clojure/exercises/anagram/README.md +13 -0
  14. data/tracks/clojure/exercises/atbash-cipher/README.md +34 -0
  15. data/tracks/clojure/exercises/bank-account/README.md +30 -0
  16. data/tracks/clojure/exercises/beer-song/README.md +327 -0
  17. data/tracks/clojure/exercises/binary/README.md +35 -0
  18. data/tracks/clojure/exercises/binary-search/README.md +41 -0
  19. data/tracks/clojure/exercises/binary-search-tree/README.md +60 -0
  20. data/tracks/clojure/exercises/bob/README.md +18 -0
  21. data/tracks/clojure/exercises/bracket-push/README.md +10 -0
  22. data/tracks/clojure/exercises/change/README.md +23 -0
  23. data/tracks/clojure/exercises/clock/README.md +13 -0
  24. data/tracks/clojure/exercises/crypto-square/README.md +74 -0
  25. data/tracks/clojure/exercises/difference-of-squares/README.md +19 -0
  26. data/tracks/clojure/exercises/etl/README.md +51 -0
  27. data/tracks/clojure/exercises/flatten-array/README.md +18 -0
  28. data/tracks/clojure/exercises/gigasecond/README.md +11 -0
  29. data/tracks/clojure/exercises/grade-school/README.md +42 -0
  30. data/tracks/clojure/exercises/grains/README.md +34 -0
  31. data/tracks/clojure/exercises/hamming/README.md +42 -0
  32. data/tracks/clojure/exercises/hello-world/README.md +51 -0
  33. data/tracks/clojure/exercises/hexadecimal/README.md +14 -0
  34. data/tracks/clojure/exercises/isogram/README.md +19 -0
  35. data/tracks/clojure/exercises/kindergarten-garden/README.md +66 -0
  36. data/tracks/clojure/exercises/largest-series-product/README.md +20 -0
  37. data/tracks/clojure/exercises/leap/README.md +33 -0
  38. data/tracks/clojure/exercises/luhn/README.md +71 -0
  39. data/tracks/clojure/exercises/meetup/README.md +30 -0
  40. data/tracks/clojure/exercises/minesweeper/README.md +30 -0
  41. data/tracks/clojure/exercises/nth-prime/README.md +15 -0
  42. data/tracks/clojure/exercises/nucleotide-count/README.md +33 -0
  43. data/tracks/clojure/exercises/octal/README.md +49 -0
  44. data/tracks/clojure/exercises/pangram/README.md +15 -0
  45. data/tracks/clojure/exercises/pascals-triangle/README.md +21 -0
  46. data/tracks/clojure/exercises/perfect-numbers/README.md +24 -0
  47. data/tracks/clojure/exercises/phone-number/README.md +34 -0
  48. data/tracks/clojure/exercises/pig-latin/README.md +24 -0
  49. data/tracks/clojure/exercises/pov/README.md +46 -0
  50. data/tracks/clojure/exercises/prime-factors/README.md +36 -0
  51. data/tracks/clojure/exercises/queen-attack/README.md +33 -0
  52. data/tracks/clojure/exercises/raindrops/README.md +24 -0
  53. data/tracks/clojure/exercises/rna-transcription/README.md +25 -0
  54. data/tracks/clojure/exercises/robot-name/README.md +22 -0
  55. data/tracks/clojure/exercises/robot-simulator/README.md +34 -0
  56. data/tracks/clojure/exercises/roman-numerals/README.md +49 -0
  57. data/tracks/clojure/exercises/rotational-cipher/README.md +36 -0
  58. data/tracks/clojure/exercises/scrabble-score/README.md +44 -0
  59. data/tracks/clojure/exercises/secret-handshake/README.md +35 -0
  60. data/tracks/clojure/exercises/sieve/README.md +34 -0
  61. data/tracks/clojure/exercises/space-age/README.md +24 -0
  62. data/tracks/clojure/exercises/strain/README.md +40 -0
  63. data/tracks/clojure/exercises/sublist/README.md +21 -0
  64. data/tracks/clojure/exercises/sum-of-multiples/README.md +18 -0
  65. data/tracks/clojure/exercises/triangle/README.md +26 -0
  66. data/tracks/clojure/exercises/trinary/README.md +28 -0
  67. data/tracks/clojure/exercises/word-count/README.md +19 -0
  68. data/tracks/clojure/exercises/wordy/README.md +63 -0
  69. data/tracks/{erlang/exercises/allergies/.meta/readme.go.tmpl → crystal/config/exercise_readme.go.tmpl} +0 -1
  70. data/tracks/crystal/config.json +0 -2
  71. data/tracks/crystal/exercises/acronym/README.md +38 -0
  72. data/tracks/crystal/exercises/anagram/README.md +36 -0
  73. data/tracks/crystal/exercises/atbash-cipher/README.md +57 -0
  74. data/tracks/crystal/exercises/binary/README.md +58 -0
  75. data/tracks/crystal/exercises/binary-search-tree/README.md +83 -0
  76. data/tracks/crystal/exercises/bob/README.md +41 -0
  77. data/tracks/crystal/exercises/bracket-push/README.md +33 -0
  78. data/tracks/crystal/exercises/difference-of-squares/README.md +42 -0
  79. data/tracks/crystal/exercises/flatten-array/README.md +41 -0
  80. data/tracks/crystal/exercises/forth/README.md +52 -0
  81. data/tracks/crystal/exercises/gigasecond/README.md +34 -0
  82. data/tracks/crystal/exercises/hamming/README.md +65 -0
  83. data/tracks/crystal/exercises/hello-world/README.md +78 -0
  84. data/tracks/crystal/exercises/largest-series-product/README.md +43 -0
  85. data/tracks/crystal/exercises/leap/README.md +56 -0
  86. data/tracks/crystal/exercises/pangram/README.md +38 -0
  87. data/tracks/crystal/exercises/pascals-triangle/README.md +44 -0
  88. data/tracks/crystal/exercises/raindrops/README.md +47 -0
  89. data/tracks/crystal/exercises/react/README.md +42 -0
  90. data/tracks/crystal/exercises/rna-transcription/README.md +48 -0
  91. data/tracks/crystal/exercises/roman-numerals/README.md +72 -0
  92. data/tracks/crystal/exercises/run-length-encoding/README.md +53 -0
  93. data/tracks/crystal/exercises/sieve/README.md +57 -0
  94. data/tracks/csharp/config.json +0 -2
  95. data/tracks/delphi/config.json +0 -2
  96. data/tracks/ecmascript/config.json +63 -2
  97. data/tracks/erlang/{exercises/anagram/.meta/readme.go.tmpl → config/exercise_readme.go.tmpl} +0 -1
  98. data/tracks/erlang/config.json +0 -2
  99. data/tracks/erlang/exercises/accumulate/README.md +0 -1
  100. data/tracks/erlang/exercises/all-your-base/README.md +0 -1
  101. data/tracks/erlang/exercises/allergies/README.md +0 -1
  102. data/tracks/erlang/exercises/anagram/README.md +0 -1
  103. data/tracks/erlang/exercises/atbash-cipher/README.md +0 -1
  104. data/tracks/erlang/exercises/bank-account/README.md +0 -1
  105. data/tracks/erlang/exercises/beer-song/README.md +0 -1
  106. data/tracks/erlang/exercises/bob/README.md +0 -1
  107. data/tracks/erlang/exercises/circular-buffer/README.md +0 -1
  108. data/tracks/erlang/exercises/clock/README.md +0 -1
  109. data/tracks/erlang/exercises/collatz-conjecture/README.md +0 -1
  110. data/tracks/erlang/exercises/difference-of-squares/README.md +0 -1
  111. data/tracks/erlang/exercises/etl/README.md +0 -1
  112. data/tracks/erlang/exercises/gigasecond/README.md +0 -1
  113. data/tracks/erlang/exercises/grade-school/README.md +0 -1
  114. data/tracks/erlang/exercises/grains/README.md +0 -1
  115. data/tracks/erlang/exercises/hamming/README.md +0 -1
  116. data/tracks/erlang/exercises/hello-world/README.md +0 -1
  117. data/tracks/erlang/exercises/largest-series-product/README.md +0 -1
  118. data/tracks/erlang/exercises/leap/README.md +0 -1
  119. data/tracks/erlang/exercises/luhn/README.md +0 -1
  120. data/tracks/erlang/exercises/meetup/README.md +0 -1
  121. data/tracks/erlang/exercises/nucleotide-count/README.md +0 -1
  122. data/tracks/erlang/exercises/parallel-letter-frequency/README.md +0 -1
  123. data/tracks/erlang/exercises/phone-number/README.md +0 -1
  124. data/tracks/erlang/exercises/rna-transcription/README.md +0 -1
  125. data/tracks/erlang/exercises/robot-simulator/README.md +0 -1
  126. data/tracks/erlang/exercises/roman-numerals/README.md +0 -1
  127. data/tracks/erlang/exercises/rotational-cipher/README.md +0 -1
  128. data/tracks/erlang/exercises/scrabble-score/README.md +0 -1
  129. data/tracks/erlang/exercises/series/README.md +0 -1
  130. data/tracks/erlang/exercises/space-age/README.md +0 -1
  131. data/tracks/erlang/exercises/spiral-matrix/README.md +0 -1
  132. data/tracks/erlang/exercises/strain/README.md +0 -1
  133. data/tracks/erlang/exercises/sum-of-multiples/README.md +0 -1
  134. data/tracks/erlang/exercises/triangle/README.md +0 -1
  135. data/tracks/erlang/exercises/word-count/README.md +0 -1
  136. data/tracks/erlang/exercises/zipper/README.md +0 -1
  137. data/tracks/factor/config.json +0 -2
  138. data/tracks/fsharp/config.json +0 -2
  139. data/tracks/go/config.json +12 -6
  140. data/tracks/go/exercises/bank-account/bank_account_test.go +60 -1
  141. data/tracks/go/exercises/error-handling/common.go +17 -0
  142. data/tracks/go/exercises/error-handling/error_handling_test.go +37 -4
  143. data/tracks/haskell/config.json +0 -2
  144. data/tracks/java/config.json +10 -2
  145. data/tracks/{erlang/exercises/accumulate → java/exercises/forth}/.meta/readme.go.tmpl +0 -0
  146. data/tracks/java/exercises/forth/README.md +41 -0
  147. data/tracks/java/exercises/forth/build.gradle +18 -0
  148. data/tracks/java/exercises/forth/src/example/java/ForthEvaluator.java +154 -0
  149. data/tracks/java/exercises/forth/src/example/java/Token.java +90 -0
  150. data/tracks/java/exercises/forth/src/main/java/.keep +0 -0
  151. data/tracks/java/exercises/forth/src/test/java/ForthEvaluatorTest.java +355 -0
  152. data/tracks/java/exercises/settings.gradle +1 -0
  153. data/tracks/javascript/config.json +0 -2
  154. data/tracks/kotlin/config.json +30 -2
  155. data/tracks/kotlin/exercises/forth/README.md +32 -0
  156. data/tracks/kotlin/exercises/forth/build.gradle +28 -0
  157. data/tracks/kotlin/exercises/forth/src/example/kotlin/ForthEvaluator.kt +138 -0
  158. data/tracks/kotlin/exercises/forth/src/main/kotlin/.keep +0 -0
  159. data/tracks/kotlin/exercises/forth/src/test/kotlin/ForthEvaluatorTest.kt +352 -0
  160. data/tracks/kotlin/exercises/meetup/README.md +33 -0
  161. data/tracks/kotlin/exercises/meetup/build.gradle +28 -0
  162. data/tracks/kotlin/exercises/meetup/src/example/kotlin/Meetup.kt +45 -0
  163. data/tracks/kotlin/exercises/meetup/src/example/kotlin/MeetupSchedule.kt +1 -0
  164. data/tracks/kotlin/exercises/meetup/src/main/kotlin/MeetupSchedule.kt +5 -0
  165. data/tracks/kotlin/exercises/meetup/src/test/kotlin/MeetupTest.kt +771 -0
  166. data/tracks/kotlin/exercises/say/README.md +72 -0
  167. data/tracks/kotlin/exercises/say/build.gradle +28 -0
  168. data/tracks/kotlin/exercises/say/src/example/kotlin/NumberSpeller.kt +88 -0
  169. data/tracks/kotlin/exercises/say/src/main/kotlin/.keep +0 -0
  170. data/tracks/kotlin/exercises/say/src/test/kotlin/NumberSpellerTest.kt +138 -0
  171. data/tracks/kotlin/exercises/settings.gradle +3 -0
  172. data/tracks/lua/config.json +0 -2
  173. data/tracks/mips/config.json +0 -2
  174. data/tracks/ocaml/config.json +0 -2
  175. data/tracks/perl5/config.json +262 -67
  176. data/tracks/perl6/config.json +98 -26
  177. data/tracks/php/docs/INSTALLATION.md +1 -1
  178. data/tracks/powershell/config.json +0 -2
  179. data/tracks/purescript/config.json +0 -2
  180. data/tracks/python/README.md +2 -2
  181. data/tracks/python/config/exercise_readme.go.tmpl +16 -0
  182. data/tracks/python/config.json +280 -15
  183. data/tracks/python/exercises/accumulate/README.md +46 -0
  184. data/tracks/python/exercises/acronym/README.md +26 -0
  185. data/tracks/python/exercises/all-your-base/README.md +46 -0
  186. data/tracks/python/exercises/allergies/README.md +48 -0
  187. data/tracks/python/exercises/alphametics/README.md +46 -0
  188. data/tracks/python/exercises/anagram/README.md +24 -0
  189. data/tracks/python/exercises/atbash-cipher/README.md +45 -0
  190. data/tracks/python/exercises/beer-song/README.md +338 -0
  191. data/tracks/python/exercises/binary/README.md +46 -0
  192. data/tracks/python/exercises/binary-search/README.md +52 -0
  193. data/tracks/python/exercises/bob/README.md +29 -0
  194. data/tracks/python/exercises/book-store/README.md +85 -0
  195. data/tracks/python/exercises/bracket-push/README.md +21 -0
  196. data/tracks/python/exercises/circular-buffer/README.md +61 -0
  197. data/tracks/python/exercises/clock/README.md +24 -0
  198. data/tracks/python/exercises/crypto-square/README.md +85 -0
  199. data/tracks/python/exercises/diamond/README.md +70 -0
  200. data/tracks/python/exercises/difference-of-squares/README.md +30 -0
  201. data/tracks/python/exercises/etl/README.md +62 -0
  202. data/tracks/python/exercises/flatten-array/README.md +29 -0
  203. data/tracks/python/exercises/gigasecond/README.md +22 -0
  204. data/tracks/python/exercises/grade-school/README.md +53 -0
  205. data/tracks/python/exercises/grains/README.md +45 -0
  206. data/tracks/python/exercises/grep/README.md +82 -0
  207. data/tracks/python/exercises/hamming/README.md +53 -0
  208. data/tracks/python/exercises/hello-world/README.md +32 -0
  209. data/tracks/python/exercises/hexadecimal/README.md +25 -0
  210. data/tracks/python/exercises/house/README.md +124 -0
  211. data/tracks/python/exercises/isogram/README.md +30 -0
  212. data/tracks/python/exercises/kindergarten-garden/README.md +77 -0
  213. data/tracks/python/exercises/largest-series-product/README.md +31 -0
  214. data/tracks/python/exercises/leap/README.md +44 -0
  215. data/tracks/python/exercises/linked-list/README.md +45 -0
  216. data/tracks/python/exercises/list-ops/README.md +21 -0
  217. data/tracks/python/exercises/luhn/README.md +82 -0
  218. data/tracks/python/exercises/matrix/README.md +56 -0
  219. data/tracks/python/exercises/meetup/README.md +41 -0
  220. data/tracks/python/exercises/minesweeper/README.md +41 -0
  221. data/tracks/python/exercises/nth-prime/README.md +26 -0
  222. data/tracks/python/exercises/nucleotide-count/README.md +44 -0
  223. data/tracks/python/exercises/ocr-numbers/README.md +96 -0
  224. data/tracks/python/exercises/octal/README.md +60 -0
  225. data/tracks/python/exercises/palindrome-products/README.md +51 -0
  226. data/tracks/python/exercises/pangram/README.md +26 -0
  227. data/tracks/python/exercises/pascals-triangle/README.md +32 -0
  228. data/tracks/python/exercises/perfect-numbers/README.md +35 -0
  229. data/tracks/python/exercises/phone-number/README.md +45 -0
  230. data/tracks/python/exercises/pig-latin/README.md +35 -0
  231. data/tracks/python/exercises/point-mutations/README.md +52 -0
  232. data/tracks/python/exercises/poker/README.md +23 -0
  233. data/tracks/python/exercises/prime-factors/README.md +47 -0
  234. data/tracks/python/exercises/protein-translation/README.md +60 -0
  235. data/tracks/python/exercises/proverb/README.md +29 -0
  236. data/tracks/python/exercises/pythagorean-triplet/README.md +35 -0
  237. data/tracks/python/exercises/queen-attack/README.md +44 -0
  238. data/tracks/python/exercises/rail-fence-cipher/README.md +71 -0
  239. data/tracks/python/exercises/raindrops/README.md +35 -0
  240. data/tracks/python/exercises/rectangles/README.md +78 -0
  241. data/tracks/python/exercises/rna-transcription/README.md +36 -0
  242. data/tracks/python/exercises/robot-name/README.md +33 -0
  243. data/tracks/python/exercises/robot-simulator/README.md +45 -0
  244. data/tracks/python/exercises/roman-numerals/README.md +60 -0
  245. data/tracks/python/exercises/rotational-cipher/README.md +47 -0
  246. data/tracks/python/exercises/run-length-encoding/README.md +41 -0
  247. data/tracks/python/exercises/saddle-points/README.md +44 -0
  248. data/tracks/python/exercises/say/README.md +80 -0
  249. data/tracks/python/exercises/scale-generator/README.md +71 -0
  250. data/tracks/python/exercises/scrabble-score/README.md +55 -0
  251. data/tracks/python/exercises/secret-handshake/README.md +46 -0
  252. data/tracks/python/exercises/series/README.md +38 -0
  253. data/tracks/python/exercises/sieve/README.md +45 -0
  254. data/tracks/python/exercises/simple-cipher/README.md +101 -0
  255. data/tracks/python/exercises/space-age/README.md +35 -0
  256. data/tracks/python/exercises/strain/README.md +51 -0
  257. data/tracks/python/exercises/sublist/README.md +32 -0
  258. data/tracks/python/exercises/sum-of-multiples/README.md +29 -0
  259. data/tracks/python/exercises/tournament/README.md +79 -0
  260. data/tracks/python/exercises/transpose/README.md +76 -0
  261. data/tracks/python/exercises/triangle/README.md +37 -0
  262. data/tracks/python/exercises/trinary/README.md +39 -0
  263. data/tracks/python/exercises/twelve-days/README.md +46 -0
  264. data/tracks/python/exercises/variable-length-quantity/README.md +50 -0
  265. data/tracks/python/exercises/word-count/README.md +30 -0
  266. data/tracks/python/exercises/word-search/README.md +41 -0
  267. data/tracks/python/exercises/wordy/README.md +74 -0
  268. data/tracks/python/exercises/zebra-puzzle/README.md +43 -0
  269. data/tracks/python/test/check-exercises.py +2 -3
  270. data/tracks/r/config.json +0 -2
  271. data/tracks/ruby/.travis.yml +1 -1
  272. data/tracks/ruby/config/exercise_readme.go.tmpl +16 -0
  273. data/tracks/ruby/config.json +265 -4
  274. data/tracks/ruby/exercises/accumulate/README.md +76 -0
  275. data/tracks/ruby/exercises/acronym/README.md +41 -0
  276. data/tracks/ruby/exercises/all-your-base/README.md +61 -0
  277. data/tracks/ruby/exercises/allergies/README.md +63 -0
  278. data/tracks/ruby/exercises/alphametics/README.md +61 -0
  279. data/tracks/ruby/exercises/anagram/README.md +39 -0
  280. data/tracks/ruby/exercises/atbash-cipher/README.md +60 -0
  281. data/tracks/ruby/exercises/beer-song/README.md +353 -0
  282. data/tracks/ruby/exercises/binary/README.md +61 -0
  283. data/tracks/ruby/exercises/binary-search/README.md +67 -0
  284. data/tracks/ruby/exercises/binary-search-tree/README.md +86 -0
  285. data/tracks/ruby/exercises/bob/README.md +44 -0
  286. data/tracks/ruby/exercises/bowling/README.md +79 -0
  287. data/tracks/ruby/exercises/bracket-push/README.md +36 -0
  288. data/tracks/ruby/exercises/circular-buffer/README.md +76 -0
  289. data/tracks/ruby/exercises/clock/README.md +39 -0
  290. data/tracks/ruby/exercises/collatz-conjecture/README.md +59 -0
  291. data/tracks/ruby/exercises/connect/README.md +60 -0
  292. data/tracks/ruby/exercises/crypto-square/README.md +100 -0
  293. data/tracks/ruby/exercises/custom-set/README.md +37 -0
  294. data/tracks/ruby/exercises/diamond/README.md +85 -0
  295. data/tracks/ruby/exercises/difference-of-squares/README.md +45 -0
  296. data/tracks/ruby/exercises/dominoes/README.md +44 -0
  297. data/tracks/ruby/exercises/etl/README.md +77 -0
  298. data/tracks/ruby/exercises/flatten-array/README.md +44 -0
  299. data/tracks/ruby/exercises/food-chain/README.md +96 -0
  300. data/tracks/ruby/exercises/gigasecond/README.md +37 -0
  301. data/tracks/ruby/exercises/grade-school/README.md +68 -0
  302. data/tracks/ruby/exercises/grains/README.md +60 -0
  303. data/tracks/ruby/exercises/hamming/README.md +68 -0
  304. data/tracks/ruby/exercises/hello-world/README.md +47 -0
  305. data/tracks/ruby/exercises/hexadecimal/README.md +40 -0
  306. data/tracks/ruby/exercises/house/README.md +139 -0
  307. data/tracks/ruby/exercises/isogram/README.md +45 -0
  308. data/tracks/ruby/exercises/kindergarten-garden/README.md +92 -0
  309. data/tracks/ruby/exercises/largest-series-product/README.md +46 -0
  310. data/tracks/ruby/exercises/leap/README.md +59 -0
  311. data/tracks/ruby/exercises/linked-list/README.md +60 -0
  312. data/tracks/ruby/exercises/list-ops/README.md +36 -0
  313. data/tracks/ruby/exercises/luhn/README.md +97 -0
  314. data/tracks/ruby/exercises/matrix/README.md +71 -0
  315. data/tracks/ruby/exercises/meetup/README.md +56 -0
  316. data/tracks/ruby/exercises/minesweeper/README.md +56 -0
  317. data/tracks/ruby/exercises/nth-prime/README.md +41 -0
  318. data/tracks/ruby/exercises/nucleotide-count/README.md +59 -0
  319. data/tracks/ruby/exercises/ocr-numbers/README.md +111 -0
  320. data/tracks/ruby/exercises/octal/README.md +75 -0
  321. data/tracks/ruby/exercises/palindrome-products/README.md +66 -0
  322. data/tracks/ruby/exercises/pangram/README.md +41 -0
  323. data/tracks/ruby/exercises/pascals-triangle/README.md +47 -0
  324. data/tracks/ruby/exercises/perfect-numbers/README.md +50 -0
  325. data/tracks/ruby/exercises/phone-number/README.md +60 -0
  326. data/tracks/ruby/exercises/pig-latin/README.md +50 -0
  327. data/tracks/ruby/exercises/point-mutations/README.md +67 -0
  328. data/tracks/ruby/exercises/poker/README.md +38 -0
  329. data/tracks/ruby/exercises/prime-factors/README.md +62 -0
  330. data/tracks/ruby/exercises/protein-translation/README.md +75 -0
  331. data/tracks/ruby/exercises/proverb/README.md +44 -0
  332. data/tracks/ruby/exercises/pythagorean-triplet/README.md +50 -0
  333. data/tracks/ruby/exercises/queen-attack/README.md +59 -0
  334. data/tracks/ruby/exercises/rail-fence-cipher/README.md +86 -0
  335. data/tracks/ruby/exercises/raindrops/README.md +50 -0
  336. data/tracks/ruby/exercises/rna-transcription/README.md +51 -0
  337. data/tracks/ruby/exercises/robot-name/README.md +57 -0
  338. data/tracks/ruby/exercises/robot-simulator/README.md +60 -0
  339. data/tracks/ruby/exercises/roman-numerals/README.md +75 -0
  340. data/tracks/ruby/exercises/run-length-encoding/README.md +56 -0
  341. data/tracks/ruby/exercises/saddle-points/README.md +59 -0
  342. data/tracks/ruby/exercises/say/README.md +95 -0
  343. data/tracks/ruby/exercises/scale-generator/README.md +86 -0
  344. data/tracks/ruby/exercises/scrabble-score/README.md +70 -0
  345. data/tracks/ruby/exercises/secret-handshake/README.md +61 -0
  346. data/tracks/ruby/exercises/series/README.md +53 -0
  347. data/tracks/ruby/exercises/sieve/README.md +60 -0
  348. data/tracks/ruby/exercises/simple-cipher/README.md +116 -0
  349. data/tracks/ruby/exercises/simple-linked-list/README.md +54 -0
  350. data/tracks/ruby/exercises/space-age/README.md +50 -0
  351. data/tracks/ruby/exercises/strain/README.md +66 -0
  352. data/tracks/ruby/exercises/sum-of-multiples/README.md +44 -0
  353. data/tracks/ruby/exercises/tournament/README.md +94 -0
  354. data/tracks/ruby/exercises/transpose/README.md +91 -0
  355. data/tracks/ruby/exercises/triangle/README.md +52 -0
  356. data/tracks/ruby/exercises/trinary/README.md +54 -0
  357. data/tracks/ruby/exercises/twelve-days/README.md +61 -0
  358. data/tracks/ruby/exercises/two-bucket/README.md +62 -0
  359. data/tracks/ruby/exercises/word-count/README.md +45 -0
  360. data/tracks/ruby/exercises/wordy/README.md +89 -0
  361. data/tracks/rust/README.md +3 -3
  362. data/tracks/rust/_test/WINDOWS_README.md +44 -0
  363. data/tracks/rust/config.json +9 -2
  364. data/tracks/rust/exercises/pig-latin/Cargo-example.toml +8 -0
  365. data/tracks/rust/exercises/pig-latin/Cargo.lock +4 -0
  366. data/tracks/rust/exercises/pig-latin/Cargo.toml +6 -0
  367. data/tracks/rust/exercises/pig-latin/README.md +56 -0
  368. data/tracks/rust/exercises/pig-latin/example.rs +28 -0
  369. data/tracks/rust/exercises/pig-latin/tests/pig-latin.rs +120 -0
  370. data/tracks/rust/problem_ordering.md +2 -2
  371. data/tracks/sml/config.json +0 -2
  372. data/tracks/swift/config/exercise_readme.go.tmpl +16 -0
  373. data/tracks/swift/config.json +304 -79
  374. data/tracks/swift/exercises/accumulate/README.md +43 -0
  375. data/tracks/swift/exercises/acronym/README.md +23 -0
  376. data/tracks/swift/exercises/all-your-base/README.md +43 -0
  377. data/tracks/swift/exercises/allergies/README.md +45 -0
  378. data/tracks/swift/exercises/anagram/README.md +21 -0
  379. data/tracks/swift/exercises/atbash-cipher/README.md +42 -0
  380. data/tracks/swift/exercises/beer-song/README.md +335 -0
  381. data/tracks/swift/exercises/binary/README.md +43 -0
  382. data/tracks/swift/exercises/binary-search/README.md +49 -0
  383. data/tracks/swift/exercises/binary-search-tree/README.md +68 -0
  384. data/tracks/swift/exercises/bob/README.md +26 -0
  385. data/tracks/swift/exercises/bowling/README.md +61 -0
  386. data/tracks/swift/exercises/bracket-push/README.md +18 -0
  387. data/tracks/swift/exercises/clock/README.md +21 -0
  388. data/tracks/swift/exercises/crypto-square/README.md +82 -0
  389. data/tracks/swift/exercises/custom-set/README.md +19 -0
  390. data/tracks/swift/exercises/difference-of-squares/README.md +27 -0
  391. data/tracks/swift/exercises/dominoes/README.md +26 -0
  392. data/tracks/swift/exercises/etl/README.md +59 -0
  393. data/tracks/swift/exercises/flatten-array/README.md +26 -0
  394. data/tracks/swift/exercises/food-chain/README.md +78 -0
  395. data/tracks/swift/exercises/gigasecond/README.md +19 -0
  396. data/tracks/swift/exercises/grade-school/README.md +50 -0
  397. data/tracks/swift/exercises/grains/README.md +42 -0
  398. data/tracks/swift/exercises/hamming/README.md +50 -0
  399. data/tracks/swift/exercises/hello-world/README.md +29 -0
  400. data/tracks/swift/exercises/hexadecimal/README.md +22 -0
  401. data/tracks/swift/exercises/house/README.md +121 -0
  402. data/tracks/swift/exercises/isogram/README.md +27 -0
  403. data/tracks/swift/exercises/kindergarten-garden/README.md +74 -0
  404. data/tracks/swift/exercises/largest-series-product/README.md +28 -0
  405. data/tracks/swift/exercises/leap/README.md +41 -0
  406. data/tracks/swift/exercises/linked-list/README.md +42 -0
  407. data/tracks/swift/exercises/luhn/README.md +79 -0
  408. data/tracks/swift/exercises/matrix/README.md +53 -0
  409. data/tracks/swift/exercises/meetup/README.md +38 -0
  410. data/tracks/swift/exercises/minesweeper/README.md +38 -0
  411. data/tracks/swift/exercises/nth-prime/README.md +23 -0
  412. data/tracks/swift/exercises/nucleotide-count/README.md +41 -0
  413. data/tracks/swift/exercises/ocr-numbers/README.md +93 -0
  414. data/tracks/swift/exercises/octal/README.md +57 -0
  415. data/tracks/swift/exercises/palindrome-products/README.md +48 -0
  416. data/tracks/swift/exercises/pangram/README.md +23 -0
  417. data/tracks/swift/exercises/pascals-triangle/README.md +29 -0
  418. data/tracks/swift/exercises/perfect-numbers/README.md +32 -0
  419. data/tracks/swift/exercises/phone-number/README.md +42 -0
  420. data/tracks/swift/exercises/pig-latin/README.md +32 -0
  421. data/tracks/swift/exercises/poker/README.md +20 -0
  422. data/tracks/swift/exercises/prime-factors/README.md +44 -0
  423. data/tracks/swift/exercises/pythagorean-triplet/README.md +32 -0
  424. data/tracks/swift/exercises/queen-attack/README.md +41 -0
  425. data/tracks/swift/exercises/raindrops/README.md +32 -0
  426. data/tracks/swift/exercises/rna-transcription/README.md +33 -0
  427. data/tracks/swift/exercises/robot-name/README.md +30 -0
  428. data/tracks/swift/exercises/robot-simulator/README.md +42 -0
  429. data/tracks/swift/exercises/roman-numerals/README.md +57 -0
  430. data/tracks/swift/exercises/run-length-encoding/README.md +38 -0
  431. data/tracks/swift/exercises/saddle-points/README.md +41 -0
  432. data/tracks/swift/exercises/scrabble-score/README.md +52 -0
  433. data/tracks/swift/exercises/secret-handshake/README.md +43 -0
  434. data/tracks/swift/exercises/series/README.md +35 -0
  435. data/tracks/swift/exercises/sieve/README.md +42 -0
  436. data/tracks/swift/exercises/simple-cipher/README.md +98 -0
  437. data/tracks/swift/exercises/simple-linked-list/README.md +36 -0
  438. data/tracks/swift/exercises/space-age/README.md +32 -0
  439. data/tracks/swift/exercises/strain/README.md +48 -0
  440. data/tracks/swift/exercises/sublist/README.md +29 -0
  441. data/tracks/swift/exercises/sum-of-multiples/README.md +26 -0
  442. data/tracks/swift/exercises/tournament/README.md +76 -0
  443. data/tracks/swift/exercises/transpose/README.md +73 -0
  444. data/tracks/swift/exercises/triangle/README.md +34 -0
  445. data/tracks/swift/exercises/trinary/README.md +36 -0
  446. data/tracks/swift/exercises/twelve-days/README.md +43 -0
  447. data/tracks/swift/exercises/word-count/README.md +27 -0
  448. data/tracks/swift/exercises/wordy/README.md +71 -0
  449. data/tracks/typescript/README.md +1 -1
  450. data/tracks/typescript/config.json +63 -3
  451. data/tracks/vimscript/config.json +0 -2
  452. metadata +371 -40
  453. data/tracks/erlang/exercises/atbash-cipher/.meta/readme.go.tmpl +0 -17
  454. data/tracks/erlang/exercises/bank-account/.meta/readme.go.tmpl +0 -17
  455. data/tracks/erlang/exercises/beer-song/.meta/readme.go.tmpl +0 -17
  456. data/tracks/erlang/exercises/bob/.meta/readme.go.tmpl +0 -17
  457. data/tracks/erlang/exercises/circular-buffer/.meta/readme.go.tmpl +0 -17
  458. data/tracks/erlang/exercises/clock/.meta/readme.go.tmpl +0 -17
  459. data/tracks/erlang/exercises/collatz-conjecture/.meta/readme.go.tmpl +0 -17
  460. data/tracks/erlang/exercises/difference-of-squares/.meta/readme.go.tmpl +0 -17
  461. data/tracks/erlang/exercises/etl/.meta/readme.go.tmpl +0 -17
  462. data/tracks/erlang/exercises/gigasecond/.meta/readme.go.tmpl +0 -17
  463. data/tracks/erlang/exercises/grade-school/.meta/readme.go.tmpl +0 -17
  464. data/tracks/erlang/exercises/grains/.meta/readme.go.tmpl +0 -17
  465. data/tracks/erlang/exercises/hamming/.meta/readme.go.tmpl +0 -17
  466. data/tracks/erlang/exercises/hello-world/.meta/readme.go.tmpl +0 -17
  467. data/tracks/erlang/exercises/largest-series-product/.meta/readme.go.tmpl +0 -17
  468. data/tracks/erlang/exercises/leap/.meta/readme.go.tmpl +0 -17
  469. data/tracks/erlang/exercises/luhn/.meta/readme.go.tmpl +0 -17
  470. data/tracks/erlang/exercises/meetup/.meta/readme.go.tmpl +0 -17
  471. data/tracks/erlang/exercises/nucleotide-count/.meta/readme.go.tmpl +0 -17
  472. data/tracks/erlang/exercises/parallel-letter-frequency/.meta/readme.go.tmpl +0 -17
  473. data/tracks/erlang/exercises/phone-number/.meta/readme.go.tmpl +0 -17
  474. data/tracks/erlang/exercises/rna-transcription/.meta/readme.go.tmpl +0 -17
  475. data/tracks/erlang/exercises/robot-simulator/.meta/readme.go.tmpl +0 -17
  476. data/tracks/erlang/exercises/roman-numerals/.meta/readme.go.tmpl +0 -17
  477. data/tracks/erlang/exercises/rotational-cipher/.meta/readme.go.tmpl +0 -17
  478. data/tracks/erlang/exercises/scrabble-score/.meta/readme.go.tmpl +0 -17
  479. data/tracks/erlang/exercises/series/.meta/readme.go.tmpl +0 -17
  480. data/tracks/erlang/exercises/space-age/.meta/readme.go.tmpl +0 -17
  481. data/tracks/erlang/exercises/spiral-matrix/.meta/readme.go.tmpl +0 -17
  482. data/tracks/erlang/exercises/strain/.meta/readme.go.tmpl +0 -17
  483. data/tracks/erlang/exercises/sum-of-multiples/.meta/readme.go.tmpl +0 -17
  484. data/tracks/erlang/exercises/triangle/.meta/readme.go.tmpl +0 -17
  485. data/tracks/erlang/exercises/word-count/.meta/readme.go.tmpl +0 -17
  486. data/tracks/erlang/exercises/zipper/.meta/readme.go.tmpl +0 -17
@@ -0,0 +1,355 @@
1
+ import org.junit.Before;
2
+ import org.junit.Ignore;
3
+ import org.junit.Rule;
4
+ import org.junit.Test;
5
+ import org.junit.rules.ExpectedException;
6
+
7
+ import java.util.Arrays;
8
+ import java.util.Collections;
9
+
10
+ import static org.junit.Assert.assertEquals;
11
+
12
+ /*
13
+ * version: 1.2.0
14
+ */
15
+ public class ForthEvaluatorTest {
16
+
17
+ @Rule
18
+ public ExpectedException expectedException = ExpectedException.none();
19
+
20
+ private ForthEvaluator forthEvaluator;
21
+
22
+ @Before
23
+ public void setUp() {
24
+ forthEvaluator = new ForthEvaluator();
25
+ }
26
+
27
+ @Test
28
+ public void testEmptyProgramResultsInEmptyStack() {
29
+ assertEquals(
30
+ Collections.emptyList(),
31
+ forthEvaluator.evaluateProgram(Collections.emptyList()));
32
+ }
33
+
34
+ @Ignore("Remove to run test")
35
+ @Test
36
+ public void testNumbersAreJustPushedOntoTheStack() {
37
+ assertEquals(
38
+ Arrays.asList(1, 2, 3, 4, 5),
39
+ forthEvaluator.evaluateProgram(Collections.singletonList("1 2 3 4 5")));
40
+ }
41
+
42
+ @Ignore("Remove to run test")
43
+ @Test
44
+ public void testTwoNumbersCanBeAdded() {
45
+ assertEquals(
46
+ Collections.singletonList(3),
47
+ forthEvaluator.evaluateProgram(Collections.singletonList("1 2 +")));
48
+ }
49
+
50
+ @Ignore("Remove to run test")
51
+ @Test
52
+ public void testErrorIfAdditionAttemptedWithNothingOnTheStack() {
53
+ expectedException.expect(IllegalArgumentException.class);
54
+ expectedException.expectMessage("Addition requires that the stack contain at least 2 values");
55
+
56
+ forthEvaluator.evaluateProgram(Collections.singletonList("+"));
57
+ }
58
+
59
+ @Ignore("Remove to run test")
60
+ @Test
61
+ public void testErrorIfAdditionAttemptedWithOneNumberOnTheStack() {
62
+ expectedException.expect(IllegalArgumentException.class);
63
+ expectedException.expectMessage("Addition requires that the stack contain at least 2 values");
64
+
65
+ forthEvaluator.evaluateProgram(Collections.singletonList("1 +"));
66
+ }
67
+
68
+ @Ignore("Remove to run test")
69
+ @Test
70
+ public void testTwoNumbersCanBeSubtracted() {
71
+ assertEquals(
72
+ Collections.singletonList(-1),
73
+ forthEvaluator.evaluateProgram(Collections.singletonList("3 4 -")));
74
+ }
75
+
76
+ @Ignore("Remove to run test")
77
+ @Test
78
+ public void testErrorIfSubtractionAttemptedWithNothingOnTheStack() {
79
+ expectedException.expect(IllegalArgumentException.class);
80
+ expectedException.expectMessage("Subtraction requires that the stack contain at least 2 values");
81
+
82
+ forthEvaluator.evaluateProgram(Collections.singletonList("-"));
83
+ }
84
+
85
+ @Ignore("Remove to run test")
86
+ @Test
87
+ public void testErrorIfSubtractionAttemptedWithOneNumberOnTheStack() {
88
+ expectedException.expect(IllegalArgumentException.class);
89
+ expectedException.expectMessage("Subtraction requires that the stack contain at least 2 values");
90
+
91
+ forthEvaluator.evaluateProgram(Collections.singletonList("1 -"));
92
+ }
93
+
94
+ @Ignore("Remove to run test")
95
+ @Test
96
+ public void testTwoNumbersCanBeMultiplied() {
97
+ assertEquals(
98
+ Collections.singletonList(8),
99
+ forthEvaluator.evaluateProgram(Collections.singletonList("2 4 *")));
100
+ }
101
+
102
+ @Ignore("Remove to run test")
103
+ @Test
104
+ public void testErrorIfMultiplicationAttemptedWithNothingOnTheStack() {
105
+ expectedException.expect(IllegalArgumentException.class);
106
+ expectedException.expectMessage("Multiplication requires that the stack contain at least 2 values");
107
+
108
+ forthEvaluator.evaluateProgram(Collections.singletonList("*"));
109
+ }
110
+
111
+ @Ignore("Remove to run test")
112
+ @Test
113
+ public void testErrorIfMultiplicationAttemptedWithOneNumberOnTheStack() {
114
+ expectedException.expect(IllegalArgumentException.class);
115
+ expectedException.expectMessage("Multiplication requires that the stack contain at least 2 values");
116
+
117
+ forthEvaluator.evaluateProgram(Collections.singletonList("1 *"));
118
+ }
119
+
120
+ @Ignore("Remove to run test")
121
+ @Test
122
+ public void testTwoNumbersCanBeDivided() {
123
+ assertEquals(
124
+ Collections.singletonList(4),
125
+ forthEvaluator.evaluateProgram(Collections.singletonList("12 3 /")));
126
+ }
127
+
128
+ @Ignore("Remove to run test")
129
+ @Test
130
+ public void testThatIntegerDivisionIsUsed() {
131
+ assertEquals(
132
+ Collections.singletonList(2),
133
+ forthEvaluator.evaluateProgram(Collections.singletonList("8 3 /")));
134
+ }
135
+
136
+ @Ignore("Remove to run test")
137
+ @Test
138
+ public void testErrorIfDividingByZero() {
139
+ expectedException.expect(IllegalArgumentException.class);
140
+ expectedException.expectMessage("Division by 0 is not allowed");
141
+
142
+ forthEvaluator.evaluateProgram(Collections.singletonList("4 0 /"));
143
+ }
144
+
145
+ @Ignore("Remove to run test")
146
+ @Test
147
+ public void testErrorIfDivisionAttemptedWithNothingOnTheStack() {
148
+ expectedException.expect(IllegalArgumentException.class);
149
+ expectedException.expectMessage("Division requires that the stack contain at least 2 values");
150
+
151
+ forthEvaluator.evaluateProgram(Collections.singletonList("/"));
152
+ }
153
+
154
+ @Ignore("Remove to run test")
155
+ @Test
156
+ public void testErrorIfDivisionAttemptedWithOneNumberOnTheStack() {
157
+ expectedException.expect(IllegalArgumentException.class);
158
+ expectedException.expectMessage("Division requires that the stack contain at least 2 values");
159
+
160
+ forthEvaluator.evaluateProgram(Collections.singletonList("1 /"));
161
+ }
162
+
163
+ @Ignore("Remove to run test")
164
+ @Test
165
+ public void testCombinedAdditionAndSubtraction() {
166
+ assertEquals(
167
+ Collections.singletonList(-1),
168
+ forthEvaluator.evaluateProgram(Collections.singletonList("1 2 + 4 -")));
169
+ }
170
+
171
+ @Ignore("Remove to run test")
172
+ @Test
173
+ public void testCombinedMultiplicationAndDivision() {
174
+ assertEquals(
175
+ Collections.singletonList(2),
176
+ forthEvaluator.evaluateProgram(Collections.singletonList("2 4 * 3 /")));
177
+ }
178
+
179
+ @Ignore("Remove to run test")
180
+ @Test
181
+ public void testDupCopiesTheTopValueOnTheStack() {
182
+ assertEquals(
183
+ Arrays.asList(1, 1),
184
+ forthEvaluator.evaluateProgram(Collections.singletonList("1 DUP")));
185
+ }
186
+
187
+ @Ignore("Remove to run test")
188
+ @Test
189
+ public void testDupParsingIsCaseInsensitive() {
190
+ assertEquals(
191
+ Arrays.asList(1, 2, 2),
192
+ forthEvaluator.evaluateProgram(Collections.singletonList("1 2 Dup")));
193
+ }
194
+
195
+ @Ignore("Remove to run test")
196
+ @Test
197
+ public void testErrorIfDuplicatingAttemptedWithNothingOnTheStack() {
198
+ expectedException.expect(IllegalArgumentException.class);
199
+ expectedException.expectMessage("Duplicating requires that the stack contain at least 1 value");
200
+
201
+ forthEvaluator.evaluateProgram(Collections.singletonList("dup"));
202
+ }
203
+
204
+ @Ignore("Remove to run test")
205
+ @Test
206
+ public void testDropRemovesTheTopValueOnTheStackIfItIsTheOnlyOne() {
207
+ assertEquals(
208
+ Collections.emptyList(),
209
+ forthEvaluator.evaluateProgram(Collections.singletonList("1 drop")));
210
+ }
211
+
212
+ @Ignore("Remove to run test")
213
+ @Test
214
+ public void testDropRemovesTheTopValueOnTheStackIfItIsNotTheOnlyOne() {
215
+ assertEquals(
216
+ Collections.singletonList(1),
217
+ forthEvaluator.evaluateProgram(Collections.singletonList("1 2 drop")));
218
+ }
219
+
220
+ @Ignore("Remove to run test")
221
+ @Test
222
+ public void testErrorIfDroppingAttemptedWithNothingOnTheStack() {
223
+ expectedException.expect(IllegalArgumentException.class);
224
+ expectedException.expectMessage("Dropping requires that the stack contain at least 1 value");
225
+
226
+ forthEvaluator.evaluateProgram(Collections.singletonList("drop"));
227
+ }
228
+
229
+ @Ignore("Remove to run test")
230
+ @Test
231
+ public void testSwapSwapsTheTopTwosValueOnTheStackIfTheyAreTheOnlyOnes() {
232
+ assertEquals(
233
+ Arrays.asList(2, 1),
234
+ forthEvaluator.evaluateProgram(Collections.singletonList("1 2 swap")));
235
+ }
236
+
237
+ @Ignore("Remove to run test")
238
+ @Test
239
+ public void testSwapSwapsTheTopTwosValueOnTheStackIfTheyAreNotTheOnlyOnes() {
240
+ assertEquals(
241
+ Arrays.asList(1, 3, 2),
242
+ forthEvaluator.evaluateProgram(Collections.singletonList("1 2 3 swap")));
243
+ }
244
+
245
+ @Ignore("Remove to run test")
246
+ @Test
247
+ public void testErrorIfSwappingAttemptedWithNothingOnTheStack() {
248
+ expectedException.expect(IllegalArgumentException.class);
249
+ expectedException.expectMessage("Swapping requires that the stack contain at least 2 values");
250
+
251
+ forthEvaluator.evaluateProgram(Collections.singletonList("swap"));
252
+ }
253
+
254
+ @Ignore("Remove to run test")
255
+ @Test
256
+ public void testErrorIfSwappingAttemptedWithOneNumberOnTheStack() {
257
+ expectedException.expect(IllegalArgumentException.class);
258
+ expectedException.expectMessage("Swapping requires that the stack contain at least 2 values");
259
+
260
+ forthEvaluator.evaluateProgram(Collections.singletonList("1 swap"));
261
+ }
262
+
263
+ @Ignore("Remove to run test")
264
+ @Test
265
+ public void testOverCopiesTheSecondElementIfThereAreOnlyTwo() {
266
+ assertEquals(
267
+ Arrays.asList(1, 2, 1),
268
+ forthEvaluator.evaluateProgram(Collections.singletonList("1 2 over")));
269
+ }
270
+
271
+ @Ignore("Remove to run test")
272
+ @Test
273
+ public void testOverCopiesTheSecondElementIfThereAreMoreThanTwo() {
274
+ assertEquals(
275
+ Arrays.asList(1, 2, 3, 2),
276
+ forthEvaluator.evaluateProgram(Collections.singletonList("1 2 3 over")));
277
+ }
278
+
279
+ @Ignore("Remove to run test")
280
+ @Test
281
+ public void testErrorIfOveringAttemptedWithNothingOnTheStack() {
282
+ expectedException.expect(IllegalArgumentException.class);
283
+ expectedException.expectMessage("Overing requires that the stack contain at least 2 values");
284
+
285
+ forthEvaluator.evaluateProgram(Collections.singletonList("over"));
286
+ }
287
+
288
+ @Ignore("Remove to run test")
289
+ @Test
290
+ public void testErrorIfOveringAttemptedWithOneNumberOnTheStack() {
291
+ expectedException.expect(IllegalArgumentException.class);
292
+ expectedException.expectMessage("Overing requires that the stack contain at least 2 values");
293
+
294
+ forthEvaluator.evaluateProgram(Collections.singletonList("1 over"));
295
+ }
296
+
297
+ @Ignore("Remove to run test")
298
+ @Test
299
+ public void testUserDefinedOperatorsCanConsistOfBuiltInOperators() {
300
+ assertEquals(
301
+ Arrays.asList(1, 1, 1),
302
+ forthEvaluator.evaluateProgram(Arrays.asList(": dup-twice dup dup ;", "1 dup-twice")));
303
+ }
304
+
305
+ @Ignore("Remove to run test")
306
+ @Test
307
+ public void testUserDefinedOperatorsAreEvaluatedInTheCorrectOrder() {
308
+ assertEquals(
309
+ Arrays.asList(1, 2, 3),
310
+ forthEvaluator.evaluateProgram(Arrays.asList(": countup 1 2 3 ;", "countup")));
311
+ }
312
+
313
+ @Ignore("Remove to run test")
314
+ @Test
315
+ public void testCanRedefineAUserDefinedOperator() {
316
+ assertEquals(
317
+ Arrays.asList(1, 1, 1),
318
+ forthEvaluator.evaluateProgram(Arrays.asList(": foo dup ;", ": foo dup dup ;", "1 foo")));
319
+ }
320
+
321
+ @Ignore("Remove to run test")
322
+ @Test
323
+ public void testCanOverrideBuiltInWordOperators() {
324
+ assertEquals(
325
+ Arrays.asList(1, 1),
326
+ forthEvaluator.evaluateProgram(Arrays.asList(": swap dup ;", "1 swap")));
327
+ }
328
+
329
+ @Ignore("Remove to run test")
330
+ @Test
331
+ public void testCanOverrideBuiltInArithmeticOperators() {
332
+ assertEquals(
333
+ Collections.singletonList(12),
334
+ forthEvaluator.evaluateProgram(Arrays.asList(": + * ;", "3 4 +")));
335
+ }
336
+
337
+ @Ignore("Remove to run test")
338
+ @Test
339
+ public void testCannotRedefineNumbers() {
340
+ expectedException.expect(IllegalArgumentException.class);
341
+ expectedException.expectMessage("Cannot redefine numbers");
342
+
343
+ forthEvaluator.evaluateProgram(Collections.singletonList(": 1 2 ;"));
344
+ }
345
+
346
+ @Ignore("Remove to run test")
347
+ @Test
348
+ public void testErrorIfEvaluatingAnUndefinedOperator() {
349
+ expectedException.expect(IllegalArgumentException.class);
350
+ expectedException.expectMessage("No definition available for operator \"foo\"");
351
+
352
+ forthEvaluator.evaluateProgram(Collections.singletonList("foo"));
353
+ }
354
+
355
+ }
@@ -25,6 +25,7 @@ include 'difference-of-squares'
25
25
  include 'etl'
26
26
  include 'flatten-array'
27
27
  include 'food-chain'
28
+ include 'forth'
28
29
  include 'gigasecond'
29
30
  include 'grade-school'
30
31
  include 'hamming'
@@ -1,7 +1,5 @@
1
1
  {
2
- "slug": "javascript",
3
2
  "language": "JavaScript",
4
- "repository": "https://github.com/exercism/javascript",
5
3
  "active": true,
6
4
  "test_pattern": ".*[.]spec[.]js$",
7
5
  "exercises": [
@@ -1,7 +1,5 @@
1
1
  {
2
- "slug": "kotlin",
3
2
  "language": "Kotlin",
4
- "repository": "https://github.com/exercism/kotlin",
5
3
  "active": true,
6
4
  "foregone": [
7
5
 
@@ -479,6 +477,16 @@
479
477
 
480
478
  ]
481
479
  },
480
+ {
481
+ "uuid": "5607dae5-13aa-4cd4-8b4c-d270516182d7",
482
+ "slug": "say",
483
+ "core": false,
484
+ "unlocked_by": null,
485
+ "difficulty": 6,
486
+ "topics": [
487
+
488
+ ]
489
+ },
482
490
  {
483
491
  "uuid": "f754e1cc-cb88-4776-ab11-3e6ae8362d5a",
484
492
  "slug": "anagram",
@@ -499,6 +507,16 @@
499
507
 
500
508
  ]
501
509
  },
510
+ {
511
+ "uuid": "d617987e-64b8-4c21-89a9-66a932c4668d",
512
+ "slug": "meetup",
513
+ "core": false,
514
+ "unlocked_by": null,
515
+ "difficulty": 7,
516
+ "topics": [
517
+
518
+ ]
519
+ },
502
520
  {
503
521
  "uuid": "1dcefdea-5447-4622-a064-079aad781398",
504
522
  "slug": "clock",
@@ -539,6 +557,16 @@
539
557
 
540
558
  ]
541
559
  },
560
+ {
561
+ "uuid": "eecd4f8b-eedc-49a3-adad-49747521ef66",
562
+ "slug": "forth",
563
+ "core": false,
564
+ "unlocked_by": null,
565
+ "difficulty": 9,
566
+ "topics": [
567
+
568
+ ]
569
+ },
542
570
  {
543
571
  "uuid": "240788cd-afa5-4fd6-8df0-a158239c0610",
544
572
  "slug": "react",
@@ -0,0 +1,32 @@
1
+ # Forth
2
+
3
+ Implement an evaluator for a very simple subset of Forth.
4
+
5
+ [Forth](https://en.wikipedia.org/wiki/Forth_%28programming_language%29)
6
+ is a stack-based programming language. Implement a very basic evaluator
7
+ for a small subset of Forth.
8
+
9
+ Your evaluator has to support the following words:
10
+
11
+ - `+`, `-`, `*`, `/` (integer arithmetic)
12
+ - `DUP`, `DROP`, `SWAP`, `OVER` (stack manipulation)
13
+
14
+ Your evaluator also has to support defining new words using the
15
+ customary syntax: `: word-name definition ;`.
16
+
17
+ To keep things simple the only data type you need to support is signed
18
+ integers of at least 16 bits size.
19
+
20
+ You should use the following rules for the syntax: a number is a
21
+ sequence of one or more (ASCII) digits, a word is a sequence of one or
22
+ more letters, digits, symbols or punctuation that is not a number.
23
+ (Forth probably uses slightly different rules, but this is close
24
+ enough.)
25
+
26
+ Words are case-insensitive.
27
+
28
+
29
+
30
+
31
+ ## Submitting Incomplete Solutions
32
+ It's possible to submit an incomplete solution so you can see how others have completed the exercise.
@@ -0,0 +1,28 @@
1
+ buildscript {
2
+ ext.kotlin_version = '1.1.1'
3
+ repositories {
4
+ mavenCentral()
5
+ }
6
+ dependencies {
7
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
8
+ }
9
+ }
10
+
11
+ apply plugin: 'kotlin'
12
+
13
+ repositories {
14
+ mavenCentral()
15
+ }
16
+
17
+ dependencies {
18
+ compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
19
+
20
+ testCompile 'junit:junit:4.12'
21
+ testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
22
+ }
23
+ test {
24
+ testLogging {
25
+ exceptionFormat = 'full'
26
+ events = ["passed", "failed", "skipped"]
27
+ }
28
+ }
@@ -0,0 +1,138 @@
1
+ import java.util.*
2
+
3
+ sealed class Token {
4
+
5
+ data class OpDefToken(val newOp: String, val newOpDefTokens: List<Token>): Token() {
6
+
7
+ companion object {
8
+ fun fromString(string: String): OpDefToken {
9
+ val trimmedLine = string.substring(2..string.lastIndex - 2)
10
+ val newOpEnd = trimmedLine.indexOf(" ")
11
+
12
+ require(newOpEnd >= 0) { "Incomplete operation definition" }
13
+
14
+ val newOpToken = Token.fromString(trimmedLine.substring(0 until newOpEnd)).first()
15
+
16
+ require(newOpToken is OpToken) { "Cannot redefine numbers" }
17
+
18
+ val newOpDefTokens = Token.fromString(trimmedLine.substring(newOpEnd + 1))
19
+ return OpDefToken((newOpToken as OpToken).op, newOpDefTokens)
20
+ }
21
+ }
22
+
23
+ }
24
+
25
+ data class OpToken(val op: String): Token()
26
+ data class IntToken(val rawValue: Int): Token()
27
+
28
+ companion object {
29
+ val opChars = "A-z+/*\\-"
30
+
31
+ fun fromString(string: String): List<Token> {
32
+ return when {
33
+ string.startsWith(':') -> listOf(OpDefToken.fromString(string))
34
+ string.matches(Regex("[$opChars]+(?:-[$opChars]+)*")) -> listOf(OpToken(string.toLowerCase()))
35
+ string.matches(Regex("\\d+")) -> listOf(IntToken(string.toInt()))
36
+ else -> string.split(delimiters = " ").flatMap { Token.fromString(it) }
37
+ }
38
+ }
39
+ }
40
+
41
+ }
42
+
43
+ class ForthEvaluator {
44
+
45
+ companion object {
46
+ private val builtInOps = mapOf<String, (Deque<Int>) -> Any>(
47
+ Pair("+") { values ->
48
+ require(values.size >= 2) { "Addition requires that the stack contain at least 2 values" }
49
+ values.push(values.pop() + values.pop())
50
+ },
51
+
52
+ Pair("-") { values ->
53
+ require(values.size >= 2) { "Subtraction requires that the stack contain at least 2 values" }
54
+ val topValue = values.pop()
55
+ val secondValue = values.pop()
56
+ values.push(secondValue - topValue)
57
+ },
58
+
59
+ Pair("*") { values ->
60
+ require(values.size >= 2) { "Multiplication requires that the stack contain at least 2 values" }
61
+ values.push(values.pop() * values.pop())
62
+ },
63
+
64
+ Pair("/") { values ->
65
+ require(values.size >= 2) { "Division requires that the stack contain at least 2 values" }
66
+ val topValue = values.pop()
67
+ val secondValue = values.pop()
68
+ require(topValue != 0) { "Division by 0 is not allowed" }
69
+ values.push(secondValue / topValue)
70
+ },
71
+
72
+ Pair("dup") { values ->
73
+ require(values.isNotEmpty()) { "Duplicating requires that the stack contain at least 1 value" }
74
+ values.push(values.peek())
75
+ },
76
+
77
+ Pair("drop") { values ->
78
+ require(values.isNotEmpty()) { "Dropping requires that the stack contain at least 1 value" }
79
+ values.pop()
80
+ },
81
+
82
+ Pair("swap") { values ->
83
+ require(values.size >= 2) { "Swapping requires that the stack contain at least 2 values" }
84
+ val topValue = values.pop()
85
+ val secondValue = values.pop()
86
+ values.push(topValue)
87
+ values.push(secondValue)
88
+ },
89
+
90
+ Pair("over") { values ->
91
+ require(values.size >= 2) { "Overing requires that the stack contain at least 2 values" }
92
+ val topValue = values.pop()
93
+ val secondValue = values.peek()
94
+ values.push(topValue)
95
+ values.push(secondValue)
96
+ }
97
+ )
98
+ }
99
+
100
+ private val values = ArrayDeque<Int>()
101
+
102
+ private val tokens = mutableListOf<Token>()
103
+
104
+ private val userOps = mutableMapOf<String, List<Token>>()
105
+
106
+ fun evaluateProgram(program: List<String>): List<Int> {
107
+ parse(program)
108
+ evaluate()
109
+ return values.toList().asReversed()
110
+ }
111
+
112
+ private fun parse(program: List<String>) = tokens.addAll(program.flatMap(Token.Companion::fromString))
113
+
114
+ private fun evaluate() {
115
+ while (tokens.isNotEmpty()) {
116
+ val token = tokens.removeAt(0)
117
+
118
+ when (token) {
119
+ is Token.OpDefToken -> userOps.put(token.newOp.toLowerCase(), token.newOpDefTokens)
120
+ is Token.OpToken -> evaluateOpToken(token)
121
+ is Token.IntToken -> values.push(token.rawValue)
122
+ }
123
+ }
124
+ }
125
+
126
+ private fun evaluateOpToken(opToken: Token.OpToken) {
127
+ val op = opToken.op
128
+
129
+ if (userOps.containsKey(op)) {
130
+ userOps[op]!!.asReversed().forEach { token -> tokens.add(index = 0, element = token) }
131
+ } else if (builtInOps.containsKey(op)) {
132
+ builtInOps[op]!!.invoke(values)
133
+ } else {
134
+ throw IllegalArgumentException("No definition available for operator \"$op\"")
135
+ }
136
+ }
137
+
138
+ }