trackler 2.2.1.54 → 2.2.1.55

Sign up to get free protection for your applications and to get access to all the features.
Files changed (280) hide show
  1. checksums.yaml +4 -4
  2. data/lib/trackler/version.rb +1 -1
  3. data/problem-specifications/exercises/dominoes/description.md +3 -3
  4. data/problem-specifications/exercises/two-fer/description.md +0 -28
  5. data/tracks/c/config.json +12 -0
  6. data/tracks/c/exercises/queen-attack/README.md +65 -0
  7. data/tracks/c/exercises/queen-attack/makefile +15 -0
  8. data/tracks/c/exercises/queen-attack/src/example.c +25 -0
  9. data/tracks/c/exercises/queen-attack/src/queen_attack.h +19 -0
  10. data/tracks/c/exercises/queen-attack/test/test_queen_attack.c +190 -0
  11. data/tracks/c/exercises/queen-attack/test/vendor/unity.c +1300 -0
  12. data/tracks/c/exercises/queen-attack/test/vendor/unity.h +274 -0
  13. data/tracks/c/exercises/queen-attack/test/vendor/unity_internals.h +701 -0
  14. data/tracks/common-lisp/exercises/acronym/README.md +1 -1
  15. data/tracks/delphi/exercises/two-fer/README.md +0 -28
  16. data/tracks/ecmascript/config.json +41 -0
  17. data/tracks/ecmascript/exercises/accumulate/package.json +5 -3
  18. data/tracks/ecmascript/exercises/acronym/package.json +5 -3
  19. data/tracks/ecmascript/exercises/all-your-base/package.json +5 -3
  20. data/tracks/ecmascript/exercises/allergies/package.json +5 -3
  21. data/tracks/ecmascript/exercises/alphametics/package.json +5 -3
  22. data/tracks/ecmascript/exercises/anagram/package.json +5 -3
  23. data/tracks/ecmascript/exercises/atbash-cipher/package.json +5 -3
  24. data/tracks/ecmascript/exercises/beer-song/package.json +5 -3
  25. data/tracks/ecmascript/exercises/binary-search-tree/package.json +5 -3
  26. data/tracks/ecmascript/exercises/binary-search/package.json +5 -3
  27. data/tracks/ecmascript/exercises/binary/package.json +5 -3
  28. data/tracks/ecmascript/exercises/bob/package.json +5 -3
  29. data/tracks/ecmascript/exercises/bowling/package.json +2 -2
  30. data/tracks/ecmascript/exercises/bracket-push/package.json +5 -3
  31. data/tracks/ecmascript/exercises/change/README.md +44 -0
  32. data/tracks/ecmascript/exercises/change/change.spec.js +80 -0
  33. data/tracks/ecmascript/exercises/change/example.js +120 -0
  34. data/tracks/ecmascript/exercises/change/package.json +69 -0
  35. data/tracks/ecmascript/exercises/circular-buffer/package.json +5 -3
  36. data/tracks/ecmascript/exercises/clock/package.json +5 -3
  37. data/tracks/ecmascript/exercises/collatz-conjecture/package.json +6 -4
  38. data/tracks/ecmascript/exercises/connect/package.json +5 -3
  39. data/tracks/ecmascript/exercises/crypto-square/package.json +5 -3
  40. data/tracks/ecmascript/exercises/custom-set/package.json +5 -3
  41. data/tracks/ecmascript/exercises/diamond/package.json +5 -3
  42. data/tracks/ecmascript/exercises/difference-of-squares/package.json +5 -3
  43. data/tracks/ecmascript/exercises/diffie-hellman/package.json +5 -3
  44. data/tracks/ecmascript/exercises/etl/package.json +5 -3
  45. data/tracks/ecmascript/exercises/flatten-array/package.json +5 -3
  46. data/tracks/ecmascript/exercises/food-chain/package.json +5 -3
  47. data/tracks/ecmascript/exercises/gigasecond/package.json +5 -3
  48. data/tracks/ecmascript/exercises/grade-school/package.json +5 -3
  49. data/tracks/ecmascript/exercises/grains/package.json +5 -3
  50. data/tracks/ecmascript/exercises/hamming/package.json +5 -3
  51. data/tracks/ecmascript/exercises/hello-world/package.json +5 -3
  52. data/tracks/ecmascript/exercises/hexadecimal/package.json +5 -3
  53. data/tracks/ecmascript/exercises/isbn-verifier/README.md +62 -0
  54. data/tracks/ecmascript/exercises/isbn-verifier/example.js +17 -0
  55. data/tracks/ecmascript/exercises/isbn-verifier/isbn-verifier.spec.js +81 -0
  56. data/tracks/ecmascript/exercises/isbn-verifier/package.json +71 -0
  57. data/tracks/ecmascript/exercises/isogram/package.json +5 -3
  58. data/tracks/ecmascript/exercises/kindergarten-garden/package.json +5 -3
  59. data/tracks/ecmascript/exercises/largest-series-product/package.json +5 -3
  60. data/tracks/ecmascript/exercises/leap/package.json +5 -3
  61. data/tracks/ecmascript/exercises/linked-list/package.json +5 -3
  62. data/tracks/ecmascript/exercises/list-ops/package.json +5 -3
  63. data/tracks/ecmascript/exercises/luhn/package.json +5 -3
  64. data/tracks/ecmascript/exercises/matrix/package.json +5 -3
  65. data/tracks/ecmascript/exercises/meetup/package.json +5 -3
  66. data/tracks/ecmascript/exercises/minesweeper/package.json +5 -3
  67. data/tracks/ecmascript/exercises/nth-prime/package.json +5 -3
  68. data/tracks/ecmascript/exercises/ocr-numbers/package.json +5 -3
  69. data/tracks/ecmascript/exercises/octal/package.json +5 -3
  70. data/tracks/ecmascript/exercises/palindrome-products/package.json +5 -3
  71. data/tracks/ecmascript/exercises/pangram/package.json +5 -3
  72. data/tracks/ecmascript/exercises/pascals-triangle/package.json +5 -3
  73. data/tracks/ecmascript/exercises/perfect-numbers/package.json +5 -3
  74. data/tracks/ecmascript/exercises/phone-number/package.json +5 -3
  75. data/tracks/ecmascript/exercises/pig-latin/package.json +5 -3
  76. data/tracks/ecmascript/exercises/prime-factors/package.json +5 -3
  77. data/tracks/ecmascript/exercises/proverb/package.json +5 -3
  78. data/tracks/ecmascript/exercises/pythagorean-triplet/package.json +5 -3
  79. data/tracks/ecmascript/exercises/queen-attack/package.json +5 -3
  80. data/tracks/ecmascript/exercises/raindrops/package.json +5 -3
  81. data/tracks/ecmascript/exercises/rna-transcription/package.json +5 -3
  82. data/tracks/ecmascript/exercises/robot-name/package.json +5 -3
  83. data/tracks/ecmascript/exercises/robot-simulator/package.json +5 -3
  84. data/tracks/ecmascript/exercises/roman-numerals/package.json +5 -3
  85. data/tracks/ecmascript/exercises/run-length-encoding/package.json +5 -3
  86. data/tracks/ecmascript/exercises/saddle-points/package.json +5 -3
  87. data/tracks/ecmascript/exercises/say/package.json +5 -3
  88. data/tracks/ecmascript/exercises/scrabble-score/package.json +5 -3
  89. data/tracks/ecmascript/exercises/secret-handshake/package.json +5 -3
  90. data/tracks/ecmascript/exercises/series/package.json +5 -3
  91. data/tracks/ecmascript/exercises/sieve/package.json +5 -3
  92. data/tracks/ecmascript/exercises/simple-cipher/package.json +5 -3
  93. data/tracks/ecmascript/exercises/simple-linked-list/package.json +5 -3
  94. data/tracks/ecmascript/exercises/space-age/package.json +5 -3
  95. data/tracks/ecmascript/exercises/strain/package.json +5 -3
  96. data/tracks/ecmascript/exercises/sublist/package.json +5 -3
  97. data/tracks/ecmascript/exercises/sum-of-multiples/package.json +5 -3
  98. data/tracks/ecmascript/exercises/transpose/README.md +94 -0
  99. data/tracks/ecmascript/exercises/transpose/example.js +12 -0
  100. data/tracks/ecmascript/exercises/transpose/package.json +71 -0
  101. data/tracks/ecmascript/exercises/transpose/transpose.spec.js +67 -0
  102. data/tracks/ecmascript/exercises/triangle/package.json +5 -3
  103. data/tracks/ecmascript/exercises/trinary/package.json +5 -3
  104. data/tracks/ecmascript/exercises/twelve-days/package.json +5 -3
  105. data/tracks/ecmascript/exercises/two-bucket/package.json +5 -3
  106. data/tracks/ecmascript/exercises/two-fer/package.json +5 -3
  107. data/tracks/ecmascript/exercises/word-count/package.json +5 -3
  108. data/tracks/ecmascript/exercises/word-search/package.json +5 -3
  109. data/tracks/ecmascript/exercises/wordy/package.json +5 -3
  110. data/tracks/ecmascript/package-lock.json +6219 -0
  111. data/tracks/ecmascript/package.json +5 -3
  112. data/tracks/erlang/exercises/collatz-conjecture/src/collatz_conjecture.erl +3 -4
  113. data/tracks/erlang/exercises/collatz-conjecture/src/example.erl +3 -3
  114. data/tracks/erlang/exercises/collatz-conjecture/test/collatz_conjecture_tests.erl +13 -9
  115. data/tracks/erlang/exercises/hello-world/src/hello_world.erl +2 -2
  116. data/tracks/erlang/exercises/leap/src/example.erl +1 -1
  117. data/tracks/erlang/exercises/leap/src/leap.erl +3 -3
  118. data/tracks/erlang/exercises/leap/test/leap_tests.erl +9 -9
  119. data/tracks/erlang/testgen/src/testgen.erl +16 -13
  120. data/tracks/erlang/testgen/src/tgen.erl +65 -38
  121. data/tracks/erlang/testgen/src/tgen_collatz-conjecture.erl +38 -0
  122. data/tracks/erlang/testgen/src/tgen_hello-world.erl +11 -19
  123. data/tracks/erlang/testgen/src/tgen_leap.erl +31 -0
  124. data/tracks/erlang/testgen/src/tgs.erl +80 -0
  125. data/tracks/fsharp/exercises/alphametics/AlphameticsTest.fs +78 -23
  126. data/tracks/fsharp/exercises/anagram/AnagramTest.fs +66 -34
  127. data/tracks/fsharp/exercises/connect/ConnectTest.fs +81 -68
  128. data/tracks/fsharp/exercises/connect/Example.fs +9 -5
  129. data/tracks/fsharp/exercises/food-chain/Example.fs +5 -9
  130. data/tracks/fsharp/exercises/food-chain/FoodChain.fs +2 -2
  131. data/tracks/fsharp/exercises/food-chain/FoodChainTest.fs +143 -75
  132. data/tracks/fsharp/exercises/hamming/Example.fs +8 -4
  133. data/tracks/fsharp/exercises/hamming/Hamming.fs +1 -1
  134. data/tracks/fsharp/exercises/hamming/HammingTest.fs +53 -13
  135. data/tracks/fsharp/exercises/house/Example.fs +5 -6
  136. data/tracks/fsharp/exercises/house/House.fs +3 -1
  137. data/tracks/fsharp/exercises/house/HouseTest.fs +272 -96
  138. data/tracks/fsharp/exercises/meetup/Example.fs +1 -1
  139. data/tracks/fsharp/exercises/meetup/Meetup.fs +1 -1
  140. data/tracks/fsharp/exercises/meetup/MeetupTest.fs +384 -73
  141. data/tracks/fsharp/exercises/ocr-numbers/Example.fs +43 -35
  142. data/tracks/fsharp/exercises/ocr-numbers/OcrNumbersTest.fs +160 -125
  143. data/tracks/fsharp/exercises/two-fer/Example.fs +4 -2
  144. data/tracks/fsharp/exercises/two-fer/TwoFer.fs +1 -1
  145. data/tracks/fsharp/exercises/two-fer/TwoFerTest.fs +7 -4
  146. data/tracks/fsharp/generators/Common.fs +6 -2
  147. data/tracks/fsharp/generators/Exercise.fs +14 -13
  148. data/tracks/fsharp/generators/Generators.fs +145 -2
  149. data/tracks/fsharp/generators/Options.fs +4 -6
  150. data/tracks/fsharp/generators/Output.fs +2 -2
  151. data/tracks/fsharp/generators/Program.fs +4 -3
  152. data/tracks/java/exercises/saddle-points/README.md +1 -1
  153. data/tracks/java/exercises/two-fer/README.md +0 -28
  154. data/tracks/javascript/exercises/beer-song/example.js +18 -14
  155. data/tracks/kotlin/exercises/saddle-points/README.md +1 -1
  156. data/tracks/kotlin/exercises/two-fer/README.md +0 -28
  157. data/tracks/lua/config.json +12 -0
  158. data/tracks/lua/exercises/collatz-conjecture/README.md +43 -0
  159. data/tracks/lua/exercises/collatz-conjecture/collatz-conjecture_spec.lua +33 -0
  160. data/tracks/lua/exercises/collatz-conjecture/example.lua +16 -0
  161. data/tracks/python/config.json +4 -1
  162. data/tracks/python/exercises/binary-search/binary_search_test.py +2 -0
  163. data/tracks/python/exercises/change/change_test.py +2 -0
  164. data/tracks/python/exercises/circular-buffer/circular_buffer_test.py +56 -50
  165. data/tracks/python/exercises/forth/example.py +3 -1
  166. data/tracks/python/exercises/forth/forth_test.py +43 -26
  167. data/tracks/python/exercises/nth-prime/nth_prime.py +1 -1
  168. data/tracks/python/exercises/rna-transcription/README.md +5 -0
  169. data/tracks/python/exercises/rna-transcription/example.py +1 -1
  170. data/tracks/python/exercises/rna-transcription/rna_transcription_test.py +7 -4
  171. data/tracks/python/exercises/robot-simulator/robot_simulator_test.py +9 -7
  172. data/tracks/python/exercises/saddle-points/saddle_points_test.py +15 -5
  173. data/tracks/python/exercises/simple-cipher/simple_cipher.py +7 -1
  174. data/tracks/python/exercises/word-count/example.py +6 -4
  175. data/tracks/python/exercises/word-count/word_count_test.py +49 -22
  176. data/tracks/python/exercises/word-search/word_search_test.py +104 -12
  177. data/tracks/rust/.travis.yml +2 -0
  178. data/tracks/rust/README.md +5 -0
  179. data/tracks/rust/_test/check-exercises.sh +0 -6
  180. data/tracks/rust/_test/ensure-lib-src-rs-exist.sh +19 -0
  181. data/tracks/rust/_test/ensure-stubs-compile.sh +26 -0
  182. data/tracks/rust/config.json +12 -0
  183. data/tracks/rust/config/exercise-readme-insert.md +3 -2
  184. data/tracks/rust/docs/ABOUT.md +2 -2
  185. data/tracks/rust/docs/LEARNING.md +1 -1
  186. data/tracks/rust/docs/RESOURCES.md +1 -1
  187. data/tracks/rust/docs/TESTS.md +2 -2
  188. data/tracks/rust/exercises/accumulate/README.md +3 -2
  189. data/tracks/rust/exercises/acronym/README.md +3 -2
  190. data/tracks/rust/exercises/all-your-base/README.md +3 -2
  191. data/tracks/rust/exercises/allergies/README.md +3 -2
  192. data/tracks/rust/exercises/alphametics/README.md +3 -2
  193. data/tracks/rust/exercises/anagram/README.md +3 -2
  194. data/tracks/rust/exercises/atbash-cipher/README.md +3 -2
  195. data/tracks/rust/exercises/beer-song/README.md +3 -2
  196. data/tracks/rust/exercises/beer-song/src/lib.rs +2 -2
  197. data/tracks/rust/exercises/binary-search/README.md +3 -2
  198. data/tracks/rust/exercises/bob/README.md +3 -2
  199. data/tracks/rust/exercises/bob/src/lib.rs +1 -1
  200. data/tracks/rust/exercises/bowling/README.md +3 -2
  201. data/tracks/rust/exercises/bracket-push/HINTS.md +1 -1
  202. data/tracks/rust/exercises/bracket-push/README.md +4 -3
  203. data/tracks/rust/exercises/circular-buffer/README.md +3 -2
  204. data/tracks/rust/exercises/clock/README.md +3 -2
  205. data/tracks/rust/exercises/collatz-conjecture/README.md +3 -2
  206. data/tracks/rust/exercises/collatz-conjecture/src/lib.rs +1 -1
  207. data/tracks/rust/exercises/crypto-square/README.md +3 -2
  208. data/tracks/rust/exercises/custom-set/README.md +3 -2
  209. data/tracks/rust/exercises/decimal/.meta/ALLOWED_TO_NOT_COMPILE +2 -0
  210. data/tracks/rust/exercises/decimal/README.md +3 -2
  211. data/tracks/rust/exercises/difference-of-squares/README.md +3 -2
  212. data/tracks/rust/exercises/difference-of-squares/src/lib.rs +3 -3
  213. data/tracks/rust/exercises/dominoes/README.md +3 -2
  214. data/tracks/rust/exercises/etl/README.md +3 -2
  215. data/tracks/rust/exercises/forth/README.md +3 -2
  216. data/tracks/rust/exercises/forth/src/lib.rs +3 -0
  217. data/tracks/rust/exercises/gigasecond/README.md +3 -2
  218. data/tracks/rust/exercises/grade-school/README.md +3 -2
  219. data/tracks/rust/exercises/grains/README.md +3 -2
  220. data/tracks/rust/exercises/hamming/README.md +3 -2
  221. data/tracks/rust/exercises/hello-world/GETTING_STARTED.md +1 -1
  222. data/tracks/rust/exercises/hello-world/README.md +3 -2
  223. data/tracks/rust/exercises/hexadecimal/README.md +3 -2
  224. data/tracks/rust/exercises/isogram/.gitignore +8 -0
  225. data/tracks/rust/exercises/isogram/Cargo.toml +3 -0
  226. data/tracks/rust/exercises/isogram/README.md +52 -0
  227. data/tracks/rust/exercises/isogram/example.rs +12 -0
  228. data/tracks/rust/exercises/isogram/src/lib.rs +0 -0
  229. data/tracks/rust/exercises/isogram/tests/isogram.rs +72 -0
  230. data/tracks/rust/exercises/largest-series-product/README.md +3 -2
  231. data/tracks/rust/exercises/leap/README.md +3 -2
  232. data/tracks/rust/exercises/leap/src/lib.rs +1 -1
  233. data/tracks/rust/exercises/luhn-from/README.md +3 -2
  234. data/tracks/rust/exercises/luhn-trait/.meta/description.md +2 -2
  235. data/tracks/rust/exercises/luhn-trait/README.md +5 -4
  236. data/tracks/rust/exercises/luhn/README.md +3 -2
  237. data/tracks/rust/exercises/minesweeper/README.md +3 -2
  238. data/tracks/rust/exercises/nth-prime/README.md +3 -2
  239. data/tracks/rust/exercises/nucleotide-codons/README.md +3 -2
  240. data/tracks/rust/exercises/nucleotide-count/README.md +3 -2
  241. data/tracks/rust/exercises/ocr-numbers/README.md +3 -2
  242. data/tracks/rust/exercises/pangram/README.md +3 -2
  243. data/tracks/rust/exercises/parallel-letter-frequency/HINTS.md +1 -1
  244. data/tracks/rust/exercises/parallel-letter-frequency/README.md +4 -3
  245. data/tracks/rust/exercises/pascals-triangle/README.md +3 -2
  246. data/tracks/rust/exercises/perfect-numbers/README.md +3 -2
  247. data/tracks/rust/exercises/phone-number/README.md +3 -2
  248. data/tracks/rust/exercises/pig-latin/README.md +3 -2
  249. data/tracks/rust/exercises/poker/README.md +3 -2
  250. data/tracks/rust/exercises/prime-factors/README.md +3 -2
  251. data/tracks/rust/exercises/protein-translation/README.md +3 -2
  252. data/tracks/rust/exercises/proverb/README.md +3 -2
  253. data/tracks/rust/exercises/proverb/src/lib.rs +1 -1
  254. data/tracks/rust/exercises/pythagorean-triplet/README.md +3 -2
  255. data/tracks/rust/exercises/queen-attack/README.md +3 -2
  256. data/tracks/rust/exercises/raindrops/README.md +3 -2
  257. data/tracks/rust/exercises/raindrops/src/lib.rs +1 -1
  258. data/tracks/rust/exercises/react/README.md +3 -2
  259. data/tracks/rust/exercises/rectangles/README.md +3 -2
  260. data/tracks/rust/exercises/rna-transcription/README.md +3 -2
  261. data/tracks/rust/exercises/robot-name/README.md +3 -2
  262. data/tracks/rust/exercises/robot-simulator/README.md +3 -2
  263. data/tracks/rust/exercises/roman-numerals/README.md +3 -2
  264. data/tracks/rust/exercises/rotational-cipher/README.md +3 -2
  265. data/tracks/rust/exercises/run-length-encoding/README.md +3 -2
  266. data/tracks/rust/exercises/say/README.md +3 -2
  267. data/tracks/rust/exercises/scrabble-score/README.md +3 -2
  268. data/tracks/rust/exercises/sieve/README.md +3 -2
  269. data/tracks/rust/exercises/space-age/README.md +3 -2
  270. data/tracks/rust/exercises/sublist/README.md +3 -2
  271. data/tracks/rust/exercises/sum-of-multiples/README.md +3 -2
  272. data/tracks/rust/exercises/sum-of-multiples/src/lib.rs +1 -1
  273. data/tracks/rust/exercises/tournament/README.md +3 -2
  274. data/tracks/rust/exercises/triangle/HINTS.md +2 -2
  275. data/tracks/rust/exercises/triangle/README.md +5 -4
  276. data/tracks/rust/exercises/variable-length-quantity/README.md +3 -2
  277. data/tracks/rust/exercises/word-count/README.md +3 -2
  278. data/tracks/rust/exercises/wordy/README.md +3 -2
  279. metadata +38 -3
  280. data/tracks/ecmascript/yarn.lock +0 -3144
@@ -9,7 +9,7 @@
9
9
  "url": "https://github.com/exercism/xecmascript"
10
10
  },
11
11
  "devDependencies": {
12
- "babel-jest": "^20.0.3",
12
+ "babel-jest": "^21.2.0",
13
13
  "babel-plugin-transform-builtin-extend": "^1.1.2",
14
14
  "babel-preset-env": "^1.4.0",
15
15
  "eslint": "^3.19.0",
@@ -17,7 +17,7 @@
17
17
  "eslint-plugin-import": "^2.2.0",
18
18
  "eslint-plugin-jsx-a11y": "^5.0.1",
19
19
  "eslint-plugin-react": "^7.0.1",
20
- "jest": "^20.0.4"
20
+ "jest": "^21.2.1"
21
21
  },
22
22
  "jest": {
23
23
  "modulePathIgnorePatterns": [
@@ -37,7 +37,9 @@
37
37
  ]
38
38
  }
39
39
  ],
40
- ["transform-regenerator"]
40
+ [
41
+ "transform-regenerator"
42
+ ]
41
43
  ]
42
44
  },
43
45
  "scripts": {
@@ -2,8 +2,7 @@
2
2
 
3
3
  -export([steps/1, test_version/0]).
4
4
 
5
- steps(N) ->
6
- undefined.
7
5
 
8
- test_version() ->
9
- 1.
6
+ steps(N) -> undefined.
7
+
8
+ test_version() -> 2.
@@ -3,15 +3,15 @@
3
3
  -export([steps/1,
4
4
  test_version/0]).
5
5
 
6
- steps(N) when N =< 0 -> {error, "Only strictly positive numbers are allowed"};
6
+ steps(N) when N =< 0 -> {error, "Only positive numbers are allowed"};
7
7
  steps(N) ->
8
8
  steps(N, 0).
9
9
 
10
10
  test_version() ->
11
- 1.
11
+ 2.
12
12
 
13
13
 
14
14
 
15
15
  steps(1, Acc) -> Acc;
16
16
  steps(N, Acc) when N rem 2 =:= 0 -> steps(N div 2, Acc + 1);
17
- steps(N, Acc) -> steps(3 * N + 1, Acc + 1).
17
+ steps(N, Acc) -> steps(3 * N + 1, Acc + 1).
@@ -1,24 +1,28 @@
1
- -module('collatz_conjecture_tests').
1
+ -module(collatz_conjecture_tests).
2
2
 
3
3
  -define(TESTED_MODULE, (sut(collatz_conjecture))).
4
- -define(TEST_VERSION, 1).
4
+ -define(TEST_VERSION, 2).
5
5
  -include("exercism.hrl").
6
6
 
7
7
 
8
8
  zero_steps_for_one_test() ->
9
- ?assertEqual(0, ?TESTED_MODULE:steps(1)).
9
+ ?assertMatch(0, ?TESTED_MODULE:steps(1)).
10
10
 
11
11
  divide_if_even_test() ->
12
- ?assertEqual(4, ?TESTED_MODULE:steps(16)).
12
+ ?assertMatch(4, ?TESTED_MODULE:steps(16)).
13
13
 
14
14
  even_and_odd_steps_test() ->
15
- ?assertEqual(9, ?TESTED_MODULE:steps(12)).
15
+ ?assertMatch(9, ?TESTED_MODULE:steps(12)).
16
16
 
17
17
  large_number_of_even_and_odd_steps_test() ->
18
- ?assertEqual(152, ?TESTED_MODULE:steps(1000000)).
19
-
18
+ ?assertMatch(152, ?TESTED_MODULE:steps(1000000)).
19
+
20
20
  zero_is_an_error_test() ->
21
- ?assertEqual({error, "Only strictly positive numbers are allowed"}, ?TESTED_MODULE:steps(0)).
21
+ ?assertMatch({error,
22
+ "Only positive numbers are allowed"},
23
+ ?TESTED_MODULE:steps(0)).
22
24
 
23
25
  negative_value_is_an_error_test() ->
24
- ?assertEqual({error, "Only strictly positive numbers are allowed"}, ?TESTED_MODULE:steps(-15)).
26
+ ?assertMatch({error,
27
+ "Only positive numbers are allowed"},
28
+ ?TESTED_MODULE:steps(-15)).
@@ -2,7 +2,7 @@
2
2
 
3
3
  -export([hello/0, test_version/0]).
4
4
 
5
- hello() ->
6
- undefined.
5
+
6
+ hello() -> undefined.
7
7
 
8
8
  test_version() -> 2.
@@ -9,7 +9,7 @@ leap_year(Year) ->
9
9
  not divisible_by(Year, 100)).
10
10
 
11
11
  test_version() ->
12
- 1.
12
+ 3.
13
13
 
14
14
 
15
15
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  -export([leap_year/1, test_version/0]).
4
4
 
5
- leap_year(Year) ->
6
- undefined.
7
5
 
8
- test_version() -> 1.
6
+ leap_year(Year) -> undefined.
7
+
8
+ test_version() -> 3.
@@ -1,18 +1,18 @@
1
1
  -module(leap_tests).
2
2
 
3
3
  -define(TESTED_MODULE, (sut(leap))).
4
- -define(TEST_VERSION, 1).
4
+ -define(TEST_VERSION, 3).
5
5
  -include("exercism.hrl").
6
6
 
7
7
 
8
- leap_year_test() ->
9
- ?assert(?TESTED_MODULE:leap_year(1996)).
8
+ year_not_divisible_by_4_common_year_test() ->
9
+ ?assertNot(?TESTED_MODULE:leap_year(2015)).
10
10
 
11
- non_leap_year_test() ->
12
- ?assertNot(?TESTED_MODULE:leap_year(1997)).
11
+ year_divisible_by_4_not_divisible_by_100_leap_year_test() ->
12
+ ?assert(?TESTED_MODULE:leap_year(2020)).
13
13
 
14
- century_test() ->
15
- ?assertNot(?TESTED_MODULE:leap_year(1900)).
14
+ year_divisible_by_100_not_divisible_by_400_common_year_test() ->
15
+ ?assertNot(?TESTED_MODULE:leap_year(2100)).
16
16
 
17
- fourth_century_test() ->
18
- ?assert(?TESTED_MODULE:leap_year(2400)).
17
+ year_divisible_by_400_leap_year_test() ->
18
+ ?assert(?TESTED_MODULE:leap_year(2000)).
@@ -84,19 +84,22 @@ execute(#{command := "generate", spec_path := SpecPath, out_path := OutPath, exe
84
84
  Generators1 = lists:map(fun (Generator) -> Generator#tgen{dest = iolist_to_binary([OutPath, $/, Generator#tgen.name])} end, Generators0),
85
85
  Contents = lists:map(fun tgen:generate/1, Generators1),
86
86
  lists:map(
87
- fun
88
- (#{name := Name, impl := Impl, path := Path}) ->
89
- io:format("Writing ~s", [Name]),
90
- case file:open(Path, [write]) of
91
- {ok, IODevice} ->
92
- io:format(IODevice, "~s", [Impl]),
93
- file:close(IODevice),
94
- io:format(", finished~n");
95
- {error, Reason} ->
96
- io:format("Can not open ~p for writing because of ~p.~n", [Path, Reason])
97
- end;
98
- ({error, Reason, Path}) ->
99
- io:format("Can not open ~p for reading because of ~p.~n", [Path, Reason])
87
+ fun (Xs = [#{exercise := ExName}|_]) ->
88
+ io:format("Writing ~s", [ExName]),
89
+ lists:map(fun
90
+ (#{exercise := GName, name := Name, folder := Folder, content := Content}) ->
91
+ Path = lists:flatten(io_lib:format("~s/~s/~s/~s.erl", [OutPath, GName, Folder, Name])),
92
+ case file:open(Path, [write]) of
93
+ {ok, IODevice} ->
94
+ io:format(IODevice, "~s", [Content]),
95
+ file:close(IODevice);
96
+ {error, Reason} ->
97
+ io:format("Can not open ~p for writing because of ~p.~n", [Path, Reason])
98
+ end
99
+ end, Xs),
100
+ io:format(", finished~n");
101
+ ({error, Reason, Path}) ->
102
+ io:format("Can not open ~p for reading because of ~p.~n", [Path, Reason])
100
103
  end, Contents);
101
104
  execute(#{command := "check"}) ->
102
105
  io:format("This command has not been implemented yet");
@@ -29,9 +29,11 @@
29
29
  }.
30
30
 
31
31
  -callback available() -> boolean().
32
- -callback init(canonical_data()) -> {ok, term()}.
33
- -callback version(term()) -> string().
34
- -callback generate_test(exercise_json(), term()) -> {ok, erl_syntax:syntax_tree() | [erl_syntax:syntax_tree()]}.
32
+ -callback version() -> pos_integer().
33
+ -callback generate_test(exercise_json()) ->
34
+ {ok,
35
+ erl_syntax:syntax_tree() | [erl_syntax:syntax_tree()],
36
+ [{string() | binary(), non_neg_integer()}]}.
35
37
 
36
38
 
37
39
  -spec check(string()) -> {true, atom()} | false.
@@ -49,15 +51,9 @@ generate(Generator = #tgen{}) ->
49
51
  io:format("Generating ~s", [Generator#tgen.name]),
50
52
  case file:read_file(Generator#tgen.path) of
51
53
  {ok, Content} ->
52
- {ModName, TestModule} = process_json(Generator, Content),
53
- TestfilePath = iolist_to_binary([Generator#tgen.dest, "/test/", ModName, ".erl"]),
54
+ Files = process_json(Generator, Content),
54
55
  io:format(", finished~n"),
55
- #{
56
- name => Generator#tgen.name,
57
- module => ModName,
58
- impl => TestModule,
59
- path => TestfilePath
60
- };
56
+ Files;
61
57
  {error, Reason} ->
62
58
  io:format(", failed (~p)~n", [Reason]),
63
59
  {error, Reason, Generator#tgen.path}
@@ -69,13 +65,16 @@ process_json(#tgen{name = GName, module = Module}, Content) ->
69
65
  case jsx:decode(Content, [return_maps, {labels, attempt_atom}]) of
70
66
  _JSON = #{exercise := GName, cases := Cases} ->
71
67
  % io:format("Parsed JSON: ~p~n", [JSON]),
72
- {TestImpls, _State} = lists:foldl(fun (Spec, {Tests, State}) ->
73
- {ok, Test, NewState} = Module:generate_test(Spec, State),
74
- {[Test|Tests], NewState}
75
- end, {[], undefined}, Cases),
76
- {ModuleName, ModuleContent} = generate_module(binary_to_list(GName), TestImpls, Module:version(undefined)), % TODO: Read version dynamically and pass as Integer!
77
-
78
- {ModuleName, io_lib:format("~s", [ModuleContent])};
68
+ {TestImpls0, Props} = lists:foldl(fun (Spec, {Tests, OldProperties}) ->
69
+ {ok, Test, Properties} = Module:generate_test(Spec),
70
+ {[Test|Tests], combine(OldProperties, Properties)}
71
+ end, {[], []}, Cases),
72
+ TestImpls1 = lists:reverse(TestImpls0),
73
+ {TestModuleName, TestModuleContent} = generate_test_module(binary_to_list(GName), TestImpls1, Module:version()),
74
+ {StubModuleName, StubModuleContent} = generate_stub_module(binary_to_list(GName), Props, Module:version()),
75
+
76
+ [#{exercise => GName, name => TestModuleName, folder => "test", content => io_lib:format("~s", [TestModuleContent])},
77
+ #{exercise => GName, name => StubModuleName, folder => "src", content => io_lib:format("~s", [StubModuleContent])}];
79
78
  #{exercise := Name} ->
80
79
  io:format("Name in JSON (~p) and name for generator (~p) do not line up", [Name, GName])
81
80
  end.
@@ -92,34 +91,50 @@ slugify(Name) when is_binary(Name) ->
92
91
  list_to_binary(slugify(binary_to_list(Name)));
93
92
  slugify(Name) when is_list(Name) ->
94
93
  lists:filtermap(fun
95
- (C) when (($a =< C) and (C =< $z)) or (C == $_) -> {true, C};
94
+ (C) when (($0 =< C) and (C =< $9)) or (($a =< C) and (C =< $z)) or (C == $_) -> {true, C};
96
95
  (C) when (($A =< C) and (C =< $Z)) -> {true, C - $A + $a};
97
96
  (C) when (C == $\s) or (C == $-)-> {true, $_};
98
97
  (_) -> false
99
98
  end, Name).
100
99
 
101
- generate_module(ModuleName, Tests, Version) ->
100
+ generate_stub_module(ModuleName, Props, Version) ->
101
+ SluggedModName = slugify(ModuleName),
102
+ VersionName = "test_version",
103
+ Props1 = Props ++ [{VersionName, []}],
104
+
105
+ Funs = lists:map(fun
106
+ ({Name, []}) ->
107
+ tgs:simple_fun(Name, [tgs:atom(undefined)]);
108
+ ({Name, Args}) when is_list(Args) ->
109
+ tgs:simple_fun(Name, Args, [tgs:atom(undefined)])
110
+ end, Props) ++ [
111
+ tgs:simple_fun(VersionName, [tgs:value(Version)])],
112
+
113
+ Abstract = [
114
+ tgs:module(SluggedModName),
115
+ nl,
116
+ tgs:export(Props1),
117
+ nl,
118
+ nl
119
+ ] ++ inter(nl, Funs),
120
+
121
+ {SluggedModName, lists:flatten(
122
+ lists:map(
123
+ fun (nl) -> io_lib:format("~n", []);
124
+ (Tree) -> io_lib:format("~s~n", [erl_prettypr:format(Tree)])
125
+ end, Abstract))}.
126
+
127
+ generate_test_module(ModuleName, Tests, Version) ->
102
128
  SluggedModName = slugify(ModuleName),
103
129
 
104
130
  Abstract = [
105
- erl_syntax:attribute(
106
- erl_syntax:text("module"),
107
- [erl_syntax:atom(SluggedModName ++ "_tests")]),
131
+ tgs:module(SluggedModName ++ "_tests"),
108
132
  nl,
109
- erl_syntax:attribute(
110
- erl_syntax:text("define"), [
111
- erl_syntax:text("TESTED_MODULE"),
112
- erl_syntax:parentheses(
113
- erl_syntax:application(
114
- erl_syntax:text("sut"), [
115
- erl_syntax:atom(SluggedModName)]))]),
116
- erl_syntax:attribute(
117
- erl_syntax:text("define"), [
118
- erl_syntax:text("TEST_VERSION"),
119
- erl_syntax:text(Version)]),
120
- erl_syntax:attribute(
121
- erl_syntax:text("include"), [
122
- erl_syntax:abstract("exercism.hrl")]),
133
+ tgs:define("TESTED_MODULE",
134
+ tgs:parens(
135
+ tgs:call_fun("sut", [tgs:atom(SluggedModName)]))),
136
+ tgs:define("TEST_VERSION", tgs:value(Version)),
137
+ tgs:include("exercism.hrl"),
123
138
  nl,
124
139
  nl] ++ inter(nl, Tests),
125
140
 
@@ -131,4 +146,16 @@ generate_module(ModuleName, Tests, Version) ->
131
146
 
132
147
  inter(_, []) -> [];
133
148
  inter(_, [X]) -> [X];
134
- inter(Delim, [X|Xs]) -> [X, Delim|Xs].
149
+ inter(Delim, [X|Xs]) -> [X, Delim|inter(Delim, Xs)].
150
+
151
+ combine(List, []) -> List;
152
+ combine(List, [{Name, Arity}|Xs]) when is_list(Name) ->
153
+ combine(List, [{list_to_binary(Name), Arity}|Xs]);
154
+ combine(List, [{Name, _} = X|Xs]) when is_binary(Name) ->
155
+ List1 = insert(List, X),
156
+ combine(List1, Xs).
157
+
158
+ insert([], X) -> [X];
159
+ insert([X|_] = Xs, X) -> Xs;
160
+ insert([X|XS], Y) when X < Y -> [X|insert(XS, Y)];
161
+ insert([X|XS], Y) when X > Y -> [Y, X|XS].
@@ -0,0 +1,38 @@
1
+ -module('tgen_collatz-conjecture').
2
+
3
+ -behaviour(tgen).
4
+
5
+ -export([
6
+ available/0,
7
+ version/0,
8
+ generate_test/1
9
+ ]).
10
+
11
+ -spec available() -> true.
12
+ available() ->
13
+ true.
14
+
15
+ version() -> 2.
16
+
17
+ generate_test(#{description := Desc, expected := #{error := Message}, property := Prop, number := Num}) ->
18
+ TestName = tgen:to_test_name(Desc),
19
+ Property = binary_to_list(Prop),
20
+
21
+ Fn = tgs:simple_fun(TestName, [
22
+ tgs:call_macro("assertMatch", [
23
+ tgs:value({error, binary_to_list(Message)}),
24
+ tgs:call_macro("TESTED_MODULE:" ++ Property, [
25
+ tgs:value(Num)])])]),
26
+
27
+ {ok, Fn, [{Prop, ["N"]}]};
28
+ generate_test(#{description := Desc, expected := Exp, property := Prop, number := Num}) ->
29
+ TestName = tgen:to_test_name(Desc),
30
+ Property = binary_to_list(Prop),
31
+
32
+ Fn = tgs:simple_fun(TestName, [
33
+ tgs:call_macro("assertMatch", [
34
+ tgs:value(Exp),
35
+ tgs:call_macro("TESTED_MODULE:" ++ Property, [
36
+ tgs:value(Num)])])]),
37
+
38
+ {ok, Fn, [{Prop, ["N"]}]}.
@@ -4,32 +4,24 @@
4
4
 
5
5
  -export([
6
6
  available/0,
7
- init/1,
8
- version/1,
9
- generate_test/2
7
+ version/0,
8
+ generate_test/1
10
9
  ]).
11
10
 
12
11
  -spec available() -> true.
13
12
  available() ->
14
13
  true.
15
14
 
16
- init(Name) ->
17
- {ok, Name}.
15
+ version() -> 2.
18
16
 
19
- version(_) -> "2".
20
-
21
- generate_test(#{description := Desc, expected := Exp, property := Prop}, State) ->
17
+ generate_test(#{description := Desc, expected := Exp, property := Prop}) ->
22
18
  TestName = tgen:to_test_name(Desc),
23
19
  Expected = binary_to_list(Exp),
24
20
  Property = binary_to_list(Prop),
25
-
26
- Fn = erl_syntax:function(
27
- erl_syntax:text(TestName), [
28
- erl_syntax:clause(none, [
29
- erl_syntax:application(
30
- erl_syntax:text("?assertEqual"), [
31
- erl_syntax:abstract(Expected),
32
- erl_syntax:application(
33
- erl_syntax:text("?TESTED_MODULE:" ++ Property), [])])])]),
34
-
35
- {ok, Fn, State}.
21
+
22
+ Fn = tgs:simple_fun(TestName, [
23
+ tgs:call_macro("assertEqual", [
24
+ tgs:value(Expected),
25
+ tgs:call_macro("TESTED_MODULE:" ++ Property, [])])]),
26
+
27
+ {ok, Fn, [{Prop, []}]}.
@@ -0,0 +1,31 @@
1
+ -module('tgen_leap').
2
+
3
+ -behaviour(tgen).
4
+
5
+ -export([
6
+ available/0,
7
+ version/0,
8
+ generate_test/1
9
+ ]).
10
+
11
+ -spec available() -> true.
12
+ available() ->
13
+ true.
14
+
15
+ version() -> 3.
16
+
17
+ generate_test(#{description := Desc, expected := Exp, property := <<"leapYear">>, input := In}) ->
18
+ TestName = tgen:to_test_name(Desc),
19
+ Property = "leap_year",
20
+
21
+ Assert = case Exp of
22
+ true -> "assert";
23
+ false -> "assertNot"
24
+ end,
25
+
26
+ Fn = tgs:simple_fun(TestName, [
27
+ tgs:call_macro(Assert, [
28
+ tgs:call_macro("TESTED_MODULE:" ++ Property, [
29
+ tgs:value(In)])])]),
30
+
31
+ {ok, Fn, [{Property, ["Year"]}]}.