trackler 2.2.1.62 → 2.2.1.63

Sign up to get free protection for your applications and to get access to all the features.
Files changed (247) hide show
  1. checksums.yaml +4 -4
  2. data/lib/trackler/version.rb +1 -1
  3. data/problem-specifications/exercises/all-your-base/canonical-data.json +20 -29
  4. data/problem-specifications/exercises/forth/canonical-data.json +52 -5
  5. data/problem-specifications/exercises/isbn-verifier/canonical-data.json +15 -15
  6. data/problem-specifications/exercises/protein-translation/canonical-data.json +153 -0
  7. data/problem-specifications/exercises/reverse-string/canonical-data.json +39 -0
  8. data/problem-specifications/exercises/reverse-string/description.md +5 -0
  9. data/problem-specifications/exercises/reverse-string/metadata.yml +5 -0
  10. data/tracks/c/config.json +42 -41
  11. data/tracks/csharp/config.json +13 -0
  12. data/tracks/csharp/exercises/Exercises.sln +6 -0
  13. data/tracks/csharp/exercises/isbn-verifier/Example.cs +27 -0
  14. data/tracks/csharp/exercises/isbn-verifier/IsbnVerifier.cs +9 -0
  15. data/tracks/csharp/exercises/isbn-verifier/IsbnVerifier.csproj +19 -0
  16. data/tracks/csharp/exercises/isbn-verifier/IsbnVerifierTest.cs +84 -0
  17. data/tracks/csharp/exercises/isbn-verifier/README.md +40 -0
  18. data/tracks/csharp/generators/Exercises/IsbnVerifier.cs +15 -0
  19. data/tracks/delphi/config.json +28 -28
  20. data/tracks/erlang/config.json +10 -0
  21. data/tracks/erlang/exercises/accumulate/rebar.config +1 -1
  22. data/tracks/erlang/exercises/accumulate/test/accumulate_tests.erl +9 -7
  23. data/tracks/erlang/exercises/all-your-base/rebar.config +1 -1
  24. data/tracks/erlang/exercises/all-your-base/test/all_your_base_tests.erl +26 -24
  25. data/tracks/erlang/exercises/allergies/rebar.config +1 -1
  26. data/tracks/erlang/exercises/allergies/test/allergies_tests.erl +19 -17
  27. data/tracks/erlang/exercises/anagram/rebar.config +1 -3
  28. data/tracks/erlang/exercises/anagram/test/anagram_tests.erl +14 -12
  29. data/tracks/erlang/exercises/atbash-cipher/rebar.config +1 -1
  30. data/tracks/erlang/exercises/atbash-cipher/test/atbash_cipher_tests.erl +7 -5
  31. data/tracks/erlang/exercises/bank-account/rebar.config +1 -1
  32. data/tracks/erlang/exercises/bank-account/test/bank_account_tests.erl +52 -51
  33. data/tracks/erlang/exercises/beer-song/rebar.config +30 -0
  34. data/tracks/erlang/exercises/beer-song/test/beer_song_tests.erl +11 -10
  35. data/tracks/erlang/exercises/bob/rebar.config +1 -1
  36. data/tracks/erlang/exercises/bob/test/bob_tests.erl +33 -35
  37. data/tracks/erlang/exercises/circular-buffer/rebar.config +1 -1
  38. data/tracks/erlang/exercises/circular-buffer/test/circular_buffer_tests.erl +33 -32
  39. data/tracks/erlang/exercises/clock/rebar.config +1 -1
  40. data/tracks/erlang/exercises/clock/test/clock_tests.erl +57 -50
  41. data/tracks/erlang/exercises/collatz-conjecture/rebar.config +1 -1
  42. data/tracks/erlang/exercises/collatz-conjecture/test/collatz_conjecture_tests.erl +11 -9
  43. data/tracks/erlang/exercises/complex-numbers/rebar.config +1 -1
  44. data/tracks/erlang/exercises/complex-numbers/test/complex_numbers_tests.erl +102 -76
  45. data/tracks/erlang/exercises/custom-set/rebar.config +1 -1
  46. data/tracks/erlang/exercises/custom-set/test/custom_set_tests.erl +100 -109
  47. data/tracks/erlang/exercises/difference-of-squares/rebar.config +1 -1
  48. data/tracks/erlang/exercises/difference-of-squares/test/difference_of_squares_tests.erl +8 -7
  49. data/tracks/erlang/exercises/etl/rebar.config +1 -1
  50. data/tracks/erlang/exercises/etl/test/etl_tests.erl +6 -5
  51. data/tracks/erlang/exercises/gigasecond/rebar.config +1 -1
  52. data/tracks/erlang/exercises/gigasecond/test/gigasecond_tests.erl +9 -8
  53. data/tracks/erlang/exercises/grade-school/rebar.config +1 -1
  54. data/tracks/erlang/exercises/grade-school/test/grade_school_tests.erl +27 -23
  55. data/tracks/erlang/exercises/grains/rebar.config +1 -1
  56. data/tracks/erlang/exercises/grains/test/grains_tests.erl +7 -6
  57. data/tracks/erlang/exercises/hamming/rebar.config +1 -1
  58. data/tracks/erlang/exercises/hamming/test/hamming_tests.erl +20 -23
  59. data/tracks/erlang/exercises/hello-world/rebar.config +1 -1
  60. data/tracks/erlang/exercises/hello-world/test/hello_world_tests.erl +6 -4
  61. data/tracks/erlang/exercises/isogram/rebar.config +1 -1
  62. data/tracks/erlang/exercises/isogram/test/isogram_tests.erl +14 -12
  63. data/tracks/erlang/exercises/largest-series-product/rebar.config +1 -1
  64. data/tracks/erlang/exercises/largest-series-product/test/largest_series_product_tests.erl +22 -21
  65. data/tracks/erlang/exercises/leap/rebar.config +1 -1
  66. data/tracks/erlang/exercises/leap/test/leap_tests.erl +8 -7
  67. data/tracks/erlang/exercises/luhn/rebar.config +1 -1
  68. data/tracks/erlang/exercises/luhn/test/luhn_tests.erl +18 -16
  69. data/tracks/erlang/exercises/meetup/rebar.config +1 -1
  70. data/tracks/erlang/exercises/meetup/test/meetup_tests.erl +96 -95
  71. data/tracks/erlang/exercises/nucleotide-count/rebar.config +1 -1
  72. data/tracks/erlang/exercises/nucleotide-count/test/nucleotide_count_tests.erl +12 -11
  73. data/tracks/erlang/exercises/pangram/README.md +60 -0
  74. data/tracks/erlang/exercises/{accumulate → pangram}/include/exercism.hrl +0 -0
  75. data/tracks/erlang/exercises/{beer-song/rebar.conf → pangram/rebar.config} +0 -0
  76. data/tracks/erlang/exercises/pangram/src/example.erl +11 -0
  77. data/tracks/erlang/exercises/pangram/src/pangram.app.src +9 -0
  78. data/tracks/erlang/exercises/pangram/src/pangram.erl +8 -0
  79. data/tracks/erlang/exercises/pangram/test/pangram_tests.erl +38 -0
  80. data/tracks/erlang/exercises/parallel-letter-frequency/rebar.config +1 -1
  81. data/tracks/erlang/exercises/parallel-letter-frequency/test/parallel_letter_frequency_tests.erl +7 -6
  82. data/tracks/erlang/exercises/phone-number/rebar.config +1 -1
  83. data/tracks/erlang/exercises/phone-number/test/phone_number_tests.erl +13 -12
  84. data/tracks/erlang/exercises/rna-transcription/rebar.config +1 -1
  85. data/tracks/erlang/exercises/rna-transcription/test/rna_transcription_tests.erl +13 -11
  86. data/tracks/erlang/exercises/robot-simulator/rebar.config +1 -1
  87. data/tracks/erlang/exercises/robot-simulator/test/robot_simulator_tests.erl +70 -69
  88. data/tracks/erlang/exercises/roman-numerals/rebar.config +1 -1
  89. data/tracks/erlang/exercises/roman-numerals/test/roman_numerals_tests.erl +6 -5
  90. data/tracks/erlang/exercises/rotational-cipher/rebar.config +1 -8
  91. data/tracks/erlang/exercises/rotational-cipher/test/rotational_cipher_tests.erl +29 -27
  92. data/tracks/erlang/exercises/scrabble-score/rebar.config +1 -1
  93. data/tracks/erlang/exercises/scrabble-score/test/scrabble_score_tests.erl +6 -5
  94. data/tracks/erlang/exercises/series/rebar.config +1 -1
  95. data/tracks/erlang/exercises/series/test/series_tests.erl +6 -5
  96. data/tracks/erlang/exercises/sieve/rebar.config +1 -1
  97. data/tracks/erlang/exercises/sieve/test/sieve_tests.erl +10 -8
  98. data/tracks/erlang/exercises/space-age/rebar.config +1 -1
  99. data/tracks/erlang/exercises/space-age/test/space_age_tests.erl +20 -19
  100. data/tracks/erlang/exercises/spiral-matrix/rebar.config +1 -1
  101. data/tracks/erlang/exercises/spiral-matrix/test/spiral_matrix_tests.erl +12 -10
  102. data/tracks/erlang/exercises/strain/rebar.config +1 -1
  103. data/tracks/erlang/exercises/strain/test/strain_tests.erl +17 -16
  104. data/tracks/erlang/exercises/sum-of-multiples/rebar.config +1 -1
  105. data/tracks/erlang/exercises/sum-of-multiples/test/sum_of_multiples_tests.erl +16 -15
  106. data/tracks/erlang/exercises/triangle/rebar.config +1 -1
  107. data/tracks/erlang/exercises/triangle/test/triangle_tests.erl +20 -19
  108. data/tracks/erlang/exercises/two-fer/rebar.config +1 -1
  109. data/tracks/erlang/exercises/two-fer/test/two_fer_tests.erl +8 -7
  110. data/tracks/erlang/exercises/word-count/rebar.config +1 -1
  111. data/tracks/erlang/exercises/word-count/test/word_count_tests.erl +6 -5
  112. data/tracks/erlang/exercises/zipper/rebar.config +1 -1
  113. data/tracks/erlang/exercises/zipper/test/zipper_tests.erl +47 -46
  114. data/tracks/erlang/testgen/src/tgen.erl +8 -6
  115. data/tracks/erlang/testgen/src/tgen_bob.erl +1 -1
  116. data/tracks/erlang/testgen/src/tgen_collatz-conjecture.erl +2 -2
  117. data/tracks/erlang/testgen/src/tgen_complex-numbers.erl +11 -11
  118. data/tracks/erlang/testgen/src/tgen_custom-set.erl +14 -14
  119. data/tracks/erlang/testgen/src/tgen_hamming.erl +2 -2
  120. data/tracks/erlang/testgen/src/tgen_hello-world.erl +1 -1
  121. data/tracks/erlang/testgen/src/tgen_leap.erl +1 -1
  122. data/tracks/erlang/testgen/src/tgen_rna-transcription.erl +2 -2
  123. data/tracks/erlang/testgen/src/tgs.erl +6 -0
  124. data/tracks/fsharp/exercises/beer-song/BeerSong.fs +1 -5
  125. data/tracks/fsharp/exercises/beer-song/BeerSongTest.fs +342 -20
  126. data/tracks/fsharp/exercises/beer-song/Example.fs +16 -10
  127. data/tracks/fsharp/exercises/food-chain/Example.fs +1 -1
  128. data/tracks/fsharp/exercises/food-chain/FoodChain.fs +1 -3
  129. data/tracks/fsharp/exercises/food-chain/FoodChainTest.fs +11 -11
  130. data/tracks/fsharp/exercises/house/Example.fs +1 -1
  131. data/tracks/fsharp/exercises/house/House.fs +1 -3
  132. data/tracks/fsharp/exercises/house/HouseTest.fs +202 -202
  133. data/tracks/fsharp/exercises/proverb/Example.fs +9 -9
  134. data/tracks/fsharp/exercises/proverb/Proverb.fs +1 -3
  135. data/tracks/fsharp/exercises/proverb/ProverbTest.fs +50 -21
  136. data/tracks/fsharp/exercises/twelve-days/Example.fs +4 -4
  137. data/tracks/fsharp/exercises/twelve-days/TwelveDays.fs +2 -6
  138. data/tracks/fsharp/exercises/twelve-days/TwelveDaysTest.fs +81 -57
  139. data/tracks/fsharp/generators/Generators.fs +39 -15
  140. data/tracks/go/bin/run-generators +5 -1
  141. data/tracks/go/config.json +14 -2
  142. data/tracks/go/exercises/accumulate/example.go +2 -1
  143. data/tracks/go/exercises/zebra-puzzle/.meta/hints.md +24 -0
  144. data/tracks/go/exercises/zebra-puzzle/README.md +76 -0
  145. data/tracks/go/exercises/zebra-puzzle/example.go +256 -0
  146. data/tracks/go/exercises/zebra-puzzle/zebra_puzzle_test.go +18 -0
  147. data/tracks/haskell/exercises/forth/package.yaml +1 -1
  148. data/tracks/haskell/exercises/forth/test/Tests.hs +1 -4
  149. data/tracks/haskell/exercises/pascals-triangle/package.yaml +1 -1
  150. data/tracks/haskell/exercises/pascals-triangle/test/Tests.hs +22 -1
  151. data/tracks/java/POLICIES.md +3 -3
  152. data/tracks/java/config.json +21 -2
  153. data/tracks/java/exercises/atbash-cipher/.meta/src/reference/java/Atbash.java +12 -12
  154. data/tracks/java/exercises/protein-translation/.meta/src/reference/java/ProteinTranslator.java +47 -0
  155. data/tracks/java/exercises/protein-translation/.meta/version +1 -0
  156. data/tracks/java/exercises/protein-translation/README.md +58 -0
  157. data/tracks/java/exercises/protein-translation/build.gradle +18 -0
  158. data/tracks/java/exercises/protein-translation/src/main/java/ProteinTranslator.java +8 -0
  159. data/tracks/java/exercises/protein-translation/src/test/java/ProteinTranslatorTest.java +179 -0
  160. data/tracks/java/exercises/settings.gradle +1 -0
  161. data/tracks/javascript/.eslintignore +2 -2
  162. data/tracks/javascript/exercises/accumulate/example.js +1 -2
  163. data/tracks/javascript/exercises/grains/example.js +6 -3
  164. data/tracks/kotlin/exercises/beer-song/.meta/src/reference/kotlin/BeerSong.kt +3 -3
  165. data/tracks/kotlin/exercises/beer-song/.meta/version +1 -1
  166. data/tracks/kotlin/exercises/beer-song/README.md +1 -1
  167. data/tracks/kotlin/exercises/beer-song/src/test/kotlin/BeerSongTest.kt +6 -6
  168. data/tracks/kotlin/exercises/forth/.meta/version +1 -1
  169. data/tracks/kotlin/exercises/forth/src/test/kotlin/ForthEvaluatorTest.kt +0 -7
  170. data/tracks/kotlin/exercises/meetup/README.md +16 -12
  171. data/tracks/kotlin/exercises/nth-prime/.meta/src/reference/kotlin/Prime.kt +7 -2
  172. data/tracks/kotlin/exercises/nth-prime/.meta/version +1 -1
  173. data/tracks/kotlin/exercises/nth-prime/src/test/kotlin/PrimeTest.kt +10 -1
  174. data/tracks/kotlin/exercises/nucleotide-count/README.md +2 -2
  175. data/tracks/kotlin/exercises/pascals-triangle/.meta/src/reference/kotlin/PascalsTriangle.kt +1 -1
  176. data/tracks/kotlin/exercises/pascals-triangle/.meta/version +1 -1
  177. data/tracks/kotlin/exercises/pascals-triangle/src/test/kotlin/PascalsTriangleTest.kt +58 -1
  178. data/tracks/kotlin/exercises/sum-of-multiples/README.md +3 -3
  179. data/tracks/ocaml/exercises/forth/test.ml +1 -3
  180. data/tracks/ocaml/exercises/rectangles/example.ml +11 -11
  181. data/tracks/php/exercises/bob/example.php +2 -2
  182. data/tracks/purescript/config.json +3 -3
  183. data/tracks/python/config.json +34 -22
  184. data/tracks/python/exercises/alphametics/example.py +90 -34
  185. data/tracks/python/exercises/ocr-numbers/example.py +18 -21
  186. data/tracks/python/exercises/ocr-numbers/ocr_numbers.py +1 -5
  187. data/tracks/python/exercises/ocr-numbers/ocr_numbers_test.py +124 -106
  188. data/tracks/python/exercises/simple-linked-list/README.md +49 -0
  189. data/tracks/python/exercises/simple-linked-list/example.py +67 -0
  190. data/tracks/python/exercises/simple-linked-list/hints.md +10 -0
  191. data/tracks/python/exercises/simple-linked-list/simple_linked_list.py +33 -0
  192. data/tracks/python/exercises/simple-linked-list/simple_linked_list_test.py +112 -0
  193. data/tracks/rust/README.md +2 -0
  194. data/tracks/rust/bin/init_exercise.py +586 -0
  195. data/tracks/rust/config.json +20 -10
  196. data/tracks/rust/exercises/book-store/.gitignore +3 -0
  197. data/tracks/rust/exercises/book-store/Cargo-example.toml +7 -0
  198. data/tracks/rust/exercises/book-store/Cargo.toml +6 -0
  199. data/tracks/rust/exercises/book-store/README.md +107 -0
  200. data/tracks/rust/exercises/book-store/example.rs +187 -0
  201. data/tracks/rust/exercises/book-store/src/lib.rs +3 -0
  202. data/tracks/rust/exercises/book-store/tests/book-store.rs +130 -0
  203. data/tracks/sml/config.json +8 -8
  204. data/tracks/typescript/config.json +6 -6
  205. metadata +43 -46
  206. data/tracks/erlang/exercises/all-your-base/include/exercism.hrl +0 -11
  207. data/tracks/erlang/exercises/allergies/include/exercism.hrl +0 -11
  208. data/tracks/erlang/exercises/anagram/include/exercism.hrl +0 -11
  209. data/tracks/erlang/exercises/atbash-cipher/include/exercism.hrl +0 -11
  210. data/tracks/erlang/exercises/bank-account/include/exercism.hrl +0 -11
  211. data/tracks/erlang/exercises/beer-song/include/exercism.hrl +0 -11
  212. data/tracks/erlang/exercises/bob/include/exercism.hrl +0 -11
  213. data/tracks/erlang/exercises/circular-buffer/include/exercism.hrl +0 -11
  214. data/tracks/erlang/exercises/clock/include/exercism.hrl +0 -11
  215. data/tracks/erlang/exercises/collatz-conjecture/include/exercism.hrl +0 -11
  216. data/tracks/erlang/exercises/complex-numbers/include/exercism.hrl +0 -11
  217. data/tracks/erlang/exercises/custom-set/include/exercism.hrl +0 -11
  218. data/tracks/erlang/exercises/difference-of-squares/include/exercism.hrl +0 -11
  219. data/tracks/erlang/exercises/etl/include/exercism.hrl +0 -11
  220. data/tracks/erlang/exercises/gigasecond/include/exercism.hrl +0 -11
  221. data/tracks/erlang/exercises/grade-school/include/exercism.hrl +0 -11
  222. data/tracks/erlang/exercises/grains/include/exercism.hrl +0 -11
  223. data/tracks/erlang/exercises/hamming/include/exercism.hrl +0 -11
  224. data/tracks/erlang/exercises/hello-world/include/exercism.hrl +0 -11
  225. data/tracks/erlang/exercises/isogram/include/exercism.hrl +0 -11
  226. data/tracks/erlang/exercises/largest-series-product/include/exercism.hrl +0 -11
  227. data/tracks/erlang/exercises/leap/include/exercism.hrl +0 -11
  228. data/tracks/erlang/exercises/luhn/include/exercism.hrl +0 -11
  229. data/tracks/erlang/exercises/meetup/include/exercism.hrl +0 -11
  230. data/tracks/erlang/exercises/nucleotide-count/include/exercism.hrl +0 -11
  231. data/tracks/erlang/exercises/parallel-letter-frequency/include/exercism.hrl +0 -11
  232. data/tracks/erlang/exercises/phone-number/include/exercism.hrl +0 -11
  233. data/tracks/erlang/exercises/rna-transcription/include/exercism.hrl +0 -11
  234. data/tracks/erlang/exercises/robot-simulator/include/exercism.hrl +0 -11
  235. data/tracks/erlang/exercises/roman-numerals/include/exercism.hrl +0 -11
  236. data/tracks/erlang/exercises/rotational-cipher/include/exercism.hrl +0 -11
  237. data/tracks/erlang/exercises/scrabble-score/include/exercism.hrl +0 -11
  238. data/tracks/erlang/exercises/series/include/exercism.hrl +0 -11
  239. data/tracks/erlang/exercises/sieve/include/exercism.hrl +0 -11
  240. data/tracks/erlang/exercises/space-age/include/exercism.hrl +0 -11
  241. data/tracks/erlang/exercises/spiral-matrix/include/exercism.hrl +0 -11
  242. data/tracks/erlang/exercises/strain/include/exercism.hrl +0 -11
  243. data/tracks/erlang/exercises/sum-of-multiples/include/exercism.hrl +0 -11
  244. data/tracks/erlang/exercises/triangle/include/exercism.hrl +0 -11
  245. data/tracks/erlang/exercises/two-fer/include/exercism.hrl +0 -11
  246. data/tracks/erlang/exercises/word-count/include/exercism.hrl +0 -11
  247. data/tracks/erlang/exercises/zipper/include/exercism.hrl +0 -11
@@ -55,7 +55,7 @@
55
55
  ]
56
56
  },
57
57
  {
58
- "uuid": "7126f86c-0e7f-7080-b4cb-3c8457dfcadcfe7e446",
58
+ "uuid": "c4754efd-6d67-48bd-994e-4b07a217ffc3",
59
59
  "slug": "parallel-letter-frequency",
60
60
  "core": false,
61
61
  "unlocked_by": null,
@@ -789,7 +789,7 @@
789
789
  ]
790
790
  },
791
791
  {
792
- "uuid": "6aacc273-0a33-8180-679e-c12c440c0fcf89e1fb6",
792
+ "uuid": "aeaed0e4-0973-4035-8bc5-07480849048f",
793
793
  "slug": "tree-building",
794
794
  "core": false,
795
795
  "unlocked_by": null,
@@ -880,12 +880,24 @@
880
880
  "recursion"
881
881
  ]
882
882
  },
883
+ {
884
+ "uuid": "4c6edc8a-7bc0-4386-a653-d1091fe49301",
885
+ "slug": "simple-linked-list",
886
+ "core": false,
887
+ "unlocked_by": null,
888
+ "difficulty": 1,
889
+ "topics": [
890
+ "lists",
891
+ "algorithms",
892
+ "conditionals"
893
+ ]
894
+ },
883
895
  {
884
896
  "uuid": "ca7a8b16-e5d5-4211-84f0-2f8e35b4a665",
885
897
  "slug": "linked-list",
886
898
  "core": false,
887
- "unlocked_by": null,
888
- "difficulty": 1,
899
+ "unlocked_by": "simple-linked-list",
900
+ "difficulty": 3,
889
901
  "topics": [
890
902
  "lists",
891
903
  "algorithms",
@@ -1024,7 +1036,7 @@
1024
1036
  ]
1025
1037
  },
1026
1038
  {
1027
- "uuid": "bacb2184-025f-0980-38d6-34fb419e03a6d3d8b44",
1039
+ "uuid": "4177de10-f767-4306-b45d-5e9c08ef4753",
1028
1040
  "slug": "two-fer",
1029
1041
  "core": false,
1030
1042
  "unlocked_by": null,
@@ -1091,7 +1103,7 @@
1091
1103
  ]
1092
1104
  },
1093
1105
  {
1094
- "uuid": "8c89f739-05fb-7b80-b5f9-6ad079c750ba8302be8",
1106
+ "uuid": "6f530d0c-d13e-4270-b120-e42c16691a66",
1095
1107
  "slug": "two-bucket",
1096
1108
  "difficulty": 5,
1097
1109
  "topics": [
@@ -1101,7 +1113,7 @@
1101
1113
  ]
1102
1114
  },
1103
1115
  {
1104
- "uuid": "1818f134-0ed9-e680-9b29-45ffd2b3344b0f841c7",
1116
+ "uuid": "88610b9a-6d3e-4924-a092-6d2f907ed4e2",
1105
1117
  "slug": "markdown",
1106
1118
  "difficulty": 3,
1107
1119
  "topics": [
@@ -1109,7 +1121,7 @@
1109
1121
  ]
1110
1122
  },
1111
1123
  {
1112
- "uuid": "e348a307-078c-5280-65af-a159283d4e79438b755",
1124
+ "uuid": "14e1dfe3-a45c-40c1-bf61-2e4f0cca5579",
1113
1125
  "slug": "forth",
1114
1126
  "core": false,
1115
1127
  "unlocked_by": null,
@@ -1132,19 +1144,19 @@
1132
1144
  ]
1133
1145
  },
1134
1146
  {
1135
- "uuid": "4f5f890d-0db4-5480-f79a-21057c37871b15133dc",
1136
- "slug": "zipper",
1137
- "core": false,
1138
- "unlocked_by": null,
1139
- "difficulty": 8,
1140
- "topics": [
1141
- "recursion",
1142
- "searching",
1143
- "trees"
1144
- ]
1147
+ "uuid": "569210ea-71c1-4fd2-941e-6bf0d953019e",
1148
+ "slug": "zipper",
1149
+ "core": false,
1150
+ "unlocked_by": null,
1151
+ "difficulty": 8,
1152
+ "topics": [
1153
+ "recursion",
1154
+ "searching",
1155
+ "trees"
1156
+ ]
1145
1157
  },
1146
1158
  {
1147
- "uuid": "3a2a947a-01b3-1e80-e32b-de1756fd88365adf12e",
1159
+ "uuid": "0dac0feb-e1c8-497e-9a1b-e96e0523eea6",
1148
1160
  "slug": "error-handling",
1149
1161
  "core": false,
1150
1162
  "unlocked_by": null,
@@ -1154,7 +1166,7 @@
1154
1166
  ]
1155
1167
  },
1156
1168
  {
1157
- "uuid": "4354f631-0cf5-9980-75e7-86d1c3da1f0d3f5e619",
1169
+ "uuid": "54995590-65eb-4178-a527-0d7b1526a843",
1158
1170
  "slug": "dominoes",
1159
1171
  "core": false,
1160
1172
  "unlocked_by": null,
@@ -1165,7 +1177,7 @@
1165
1177
  ]
1166
1178
  },
1167
1179
  {
1168
- "uuid": "55c818d6-04a8-2480-de83-9f85fd0d2eafa71935f",
1180
+ "uuid": "d98b1080-36d4-4357-b12a-685d204856bf",
1169
1181
  "slug": "pov",
1170
1182
  "core": false,
1171
1183
  "unlocked_by": null,
@@ -1178,7 +1190,7 @@
1178
1190
  ]
1179
1191
  },
1180
1192
  {
1181
- "uuid": "21dacf48-0580-4d80-a6d2-257b07ad3cc47b02454",
1193
+ "uuid": "4c0d0d6b-347e-40ae-9b51-08555fe76cb9",
1182
1194
  "slug": "react",
1183
1195
  "core": false,
1184
1196
  "unlocked_by": null,
@@ -1,42 +1,98 @@
1
1
  from itertools import permutations
2
- from string import ascii_uppercase as acu, digits
2
+ from string import ascii_uppercase as acu
3
3
  acuset = set(acu)
4
- dset = set(digits)
4
+ dset = set(range(10))
5
+ nzdset = dset.copy()
6
+ nzdset.remove(0)
5
7
 
6
8
 
7
9
  def solve(an):
8
- fullexp = [tuple(map(str.strip, s.split("+")))
9
- for s in an.upper().split("==")]
10
- digexp = [[w[-1] for w in s] for s in fullexp]
10
+ # Break down to words
11
+ an = an.upper()
12
+ alphaexp = [tuple(map(str.strip, s.split("+")))
13
+ for s in an.split("==")]
14
+ # Sum powers of 10 for letters ready for computation
15
+ expdict = dict()
16
+ loexpdict = dict()
17
+ for si, s in enumerate(alphaexp):
18
+ esign = 1 - (si << 1)
19
+ for t in s:
20
+ lowletter = t[-1]
21
+ if lowletter not in loexpdict:
22
+ loexpdict[lowletter] = 0
23
+ loexpdict[lowletter] += esign
24
+ for p, letter in enumerate(reversed(t)):
25
+ if letter not in expdict:
26
+ expdict[letter] = 0
27
+ expdict[letter] += esign * (10 ** p)
11
28
 
12
- alphas = set("".join([w for s in fullexp for w in s]))
13
- if not alphas <= acuset:
29
+ # Extract all letters and check if they are really letters
30
+ alldigits = set(expdict.keys())
31
+ if not alldigits <= acuset:
14
32
  raise ValueError
15
- leadchars = set([w[0] for s in fullexp for w in s])
16
- digchars = set([x for s in digexp for x in s])
17
- leadigchars = leadchars & digchars
18
- leadigcharslen = len(leadigchars)
19
- leadother = leadchars - leadigchars
20
- leadotherlen = len(leadother)
21
-
22
- digtuple = tuple(leadigchars) + tuple(set(digchars) - leadigchars)
23
- othertuple = tuple(leadother) + tuple(alphas - digchars - leadother)
24
- combostg = "".join(digtuple + othertuple)
25
- olen = len(othertuple)
26
- for digtest in permutations(digits, len(digtuple)):
27
- if any(map(lambda x: x == "0", digtest[:leadigcharslen])):
28
- continue
29
- td = dict(zip(digtuple, digtest))
30
- digeval = [[int(td[w]) for w in s] for s in digexp]
31
- if (sum(digeval[0]) % 10) == (sum(digeval[1]) % 10):
32
- for otest in permutations(dset - set(digtest), olen):
33
- if any(map(lambda x: x == "0", otest[:leadotherlen])):
34
- continue
35
- b = an
36
- for c, v in zip(combostg, "".join(digtest + otest)):
37
- b = b.replace(c, v)
38
- fulleval = [[int(w.strip())
39
- for w in s.split("+")] for s in b.split("==")]
40
- if sum(fulleval[0]) == sum(fulleval[1]):
41
- return dict(zip(combostg, map(int, digtest + otest)))
33
+
34
+ # extract high and low digigts
35
+ hidigits = set([w[0] for s in alphaexp for w in s])
36
+ lodigits = set([w[-1] for s in alphaexp for w in s])
37
+
38
+ # Break down low digits to nonzeros (also high digits) and possible zeros
39
+ lonzdigits = lodigits & hidigits
40
+ lorestdigits = lodigits - lonzdigits
41
+
42
+ # Main digits, all but not low
43
+ maindigits = alldigits - lodigits
44
+
45
+ # Break down main digit list into nonzeroees and possible zeroes
46
+ mainnzdigits = maindigits & hidigits
47
+ mainrestdigits = maindigits - mainnzdigits
48
+
49
+ # change sets to tuples to guarantee the stable order
50
+ t_lorestdigits = tuple(lorestdigits)
51
+ t_lonzdigits = tuple(lonzdigits)
52
+ t_lowdigs = t_lorestdigits + t_lonzdigits
53
+
54
+ t_mainrestdigits = tuple(mainrestdigits)
55
+ t_mainnzdigits = tuple(mainnzdigits)
56
+ t_maindigs = t_mainrestdigits + t_mainnzdigits
57
+ t_alldigs = t_lowdigs + t_maindigs
58
+
59
+ # Check all possible digit permunations with zeros
60
+ for lorest in permutations(dset, len(lorestdigits)):
61
+ remnzdigs = nzdset - set(lorest)
62
+ # Generate addtional non-zero digit permutations
63
+ for lonz in permutations(remnzdigs, len(lonzdigits)):
64
+ # Build a dictionary for to test the expression
65
+ t_digvals = lorest + lonz
66
+ # Evaluate the expression sides
67
+ testsum = sum([dig * loexpdict[let]
68
+ for let, dig in zip(t_lowdigs, t_digvals)])
69
+ if testsum % 10 == 0:
70
+ # Low digit test passed, check the main digits
71
+ # if there are no other digits that low digits,
72
+ # test the whole expression and return if OK
73
+ if len(maindigits) == 0:
74
+ testsum = sum([dig * expdict[let]
75
+ for let, dig in zip(t_lowdigs, t_digvals)])
76
+ if testsum == 0:
77
+ return dict(zip(t_lowdigs, t_digvals))
78
+ else:
79
+ # non-assigned digits
80
+ remdigs = dset - set(t_digvals)
81
+ # non-assigned without 0
82
+ remnzdigs = remdigs - set((0,))
83
+ # permutations for the rest of the digits
84
+ for mainrest in permutations(remdigs,
85
+ len(t_mainrestdigits)):
86
+ lastnzdigs = remnzdigs - set(mainrest)
87
+ # permutations for the non-zero rest of the digits
88
+ for mainnz in permutations(lastnzdigs,
89
+ len(t_mainnzdigits)):
90
+ # Evaluate
91
+ t_alldigvals = lorest + lonz + mainrest + mainnz
92
+ testsum = sum([dig * expdict[let]
93
+ for let, dig in zip(t_alldigs,
94
+ t_alldigvals)])
95
+ if testsum == 0:
96
+ return dict(zip(t_alldigs, t_alldigvals))
97
+
42
98
  return {}
@@ -1,10 +1,10 @@
1
- ROW = 4
2
- COL = 3
1
+ NUM_ROWS = 4
2
+ NUM_COLS = 3
3
3
 
4
4
 
5
5
  def split_ocr(ocr):
6
- return [[ocr[i][COL * j:COL * (j + 1)] for i in range(ROW)]
7
- for j in range(len(ocr[0]) // COL)]
6
+ return [[ocr[i][NUM_COLS * j:NUM_COLS * (j + 1)] for i in range(NUM_ROWS)]
7
+ for j in range(len(ocr[0]) // NUM_COLS)]
8
8
 
9
9
 
10
10
  ALL = [' _ _ _ _ _ _ _ _ ',
@@ -16,11 +16,21 @@ OCR_LIST = split_ocr(ALL)
16
16
  OCR_LIST = [OCR_LIST[-1]] + OCR_LIST[:9]
17
17
 
18
18
 
19
- def number(ocr):
20
- if (len(ocr) != ROW or len(ocr[0]) % COL or
21
- any(len(r) != len(ocr[0]) for r in ocr)):
19
+ def convert(input_grid):
20
+ split_indices = (list(range(0, len(input_grid), NUM_ROWS)) +
21
+ [len(input_grid)])
22
+
23
+ lines = [input_grid[start:end]
24
+ for start, end in zip(split_indices[:-1], split_indices[1:])]
25
+
26
+ return ",".join(convert_one_line(line) for line in lines)
27
+
28
+
29
+ def convert_one_line(input_grid):
30
+ if (len(input_grid) != NUM_ROWS or len(input_grid[0]) % NUM_COLS or
31
+ any(len(r) != len(input_grid[0]) for r in input_grid)):
22
32
  raise ValueError('Wrong grid size.')
23
- numbers = split_ocr(ocr)
33
+ numbers = split_ocr(input_grid)
24
34
  digits = ''
25
35
  for n in numbers:
26
36
  try:
@@ -28,16 +38,3 @@ def number(ocr):
28
38
  except ValueError:
29
39
  digits += '?'
30
40
  return digits
31
-
32
-
33
- def grid(digits):
34
- try:
35
- if not digits.isdigit():
36
- raise ValueError('String should be numeric.')
37
- except AttributeError:
38
- raise ValueError('Argument should be a string.')
39
- ocr = ['' for i in range(ROW)]
40
- for d in digits:
41
- for r in range(ROW):
42
- ocr[r] += OCR_LIST[int(d)][r]
43
- return ocr
@@ -1,6 +1,2 @@
1
- def number(digits):
2
- pass
3
-
4
-
5
- def grid(digits):
1
+ def convert(input_grid):
6
2
  pass
@@ -1,123 +1,141 @@
1
1
  """Tests for the ocr-numbers exercise
2
2
 
3
3
  Implementation note:
4
- Both ocr.grid and ocr.number should validate their input
5
- and raise ValueErrors with meaningful error messages
4
+ ocr.convert should validate its input and
5
+ raise ValueErrors with meaningful error messages
6
6
  if necessary.
7
7
  """
8
8
 
9
9
  import unittest
10
10
 
11
- from ocr_numbers import grid, number
11
+ from ocr_numbers import convert
12
12
 
13
13
 
14
+ # Tests adapted from `problem-specifications//canonical-data.json` @ v1.0.0
15
+
14
16
  class OcrTest(unittest.TestCase):
15
- def test_0(self):
16
- self.assertEqual(number([" _ ",
17
- "| |",
18
- "|_|",
19
- " "]), '0')
20
-
21
- def test_1(self):
22
- self.assertEqual(number([" ",
23
- " |",
24
- " |",
25
- " "]), '1')
26
-
27
- def test_garbage(self):
28
- self.assertEqual(number([" _ ",
29
- " _|",
30
- " |",
31
- " "]), '?')
32
-
33
- def test_last_line_nonblank(self):
34
- self.assertEqual(number([" ",
35
- " |",
36
- " |",
37
- "| |"]), '?')
38
-
39
- def test_unknown_char(self):
40
- self.assertEqual(number([" - ",
41
- " _|",
42
- " X|",
43
- " "]), '?')
44
-
45
- def test_too_short_row(self):
17
+ def test_recognizes_0(self):
18
+ self.assertEqual(convert([" _ ",
19
+ "| |",
20
+ "|_|",
21
+ " "]), '0')
22
+
23
+ def test_recognizes_1(self):
24
+ self.assertEqual(convert([" ",
25
+ " |",
26
+ " |",
27
+ " "]), '1')
28
+
29
+ def test_unreadable(self):
30
+ self.assertEqual(convert([" ",
31
+ " _",
32
+ " |",
33
+ " "]), '?')
34
+
35
+ def test_line_number_not_multiple_of_four(self):
46
36
  with self.assertRaises(ValueError):
47
- number([" ",
48
- " _|",
49
- " |",
50
- " "])
37
+ convert([" _ ",
38
+ "| |",
39
+ " "])
51
40
 
52
- def test_insufficient_rows(self):
53
- with self.assertRaises(ValueError):
54
- number([" ",
55
- " _|",
56
- " X|"])
57
-
58
- def test_grid0(self):
59
- self.assertEqual(grid('0'), [" _ ",
60
- "| |",
61
- "|_|",
62
- " "])
63
-
64
- def test_grid1(self):
65
- self.assertEqual(grid('1'), [" ",
66
- " |",
67
- " |",
68
- " "])
69
-
70
- def test_0010110(self):
71
- self.assertEqual(
72
- number([
73
- " _ _ _ _ ",
74
- "| || | || | | || |",
75
- "|_||_| ||_| | ||_|",
76
- " "
77
- ]), '0010110')
78
-
79
- def test_3186547290(self):
80
- digits = '3186547290'
81
- self.assertEqual(
82
- number([
83
- " _ _ _ _ _ _ _ _ ",
84
- " _| ||_||_ |_ |_| | _||_|| |",
85
- " _| ||_||_| _| | ||_ _||_|",
86
- " "
87
- ]), digits)
88
-
89
- def test_Lost(self):
90
- digits = '4815162342'
91
- self.assertEqual(
92
- number([
93
- " _ _ _ _ _ _ ",
94
- "|_||_| ||_ ||_ _| _||_| _|",
95
- " ||_| | _| ||_||_ _| ||_ ",
96
- " "
97
- ]), digits)
98
-
99
- def test_garble_middle(self):
100
- self.assertEqual(
101
- number([
102
- " _ _ _ ",
103
- " | _| ||_||_ ",
104
- " ||_ _| | _|",
105
- " "
106
- ]), '12?45')
107
-
108
- def test_grid3186547290(self):
109
- digits = '3186547290'
110
- self.assertEqual(
111
- grid(digits), [
112
- " _ _ _ _ _ _ _ _ ",
113
- " _| ||_||_ |_ |_| | _||_|| |",
114
- " _| ||_||_| _| | ||_ _||_|",
115
- " "
116
- ])
117
-
118
- def test_invalid_grid(self):
41
+ def test_col_number_not_multiple_of_three(self):
119
42
  with self.assertRaises(ValueError):
120
- grid('123a')
43
+ convert([" ",
44
+ " |",
45
+ " |",
46
+ " "])
47
+
48
+ def test_recognizes_110101100(self):
49
+ input_grid = [
50
+ " _ _ _ _ ",
51
+ " | || | || | | || || |",
52
+ " | ||_| ||_| | ||_||_|",
53
+ " "
54
+ ]
55
+ self.assertEqual(convert(input_grid), "110101100")
56
+
57
+ def test_garbled_numbers_in_string(self):
58
+ input_grid = [
59
+ " _ _ _ ",
60
+ " | || | || | || || |",
61
+ " | | _| ||_| | ||_||_|",
62
+ " "
63
+ ]
64
+ self.assertEqual(convert(input_grid), "11?10?1?0")
65
+
66
+ def test_recognizes_2(self):
67
+ self.assertEqual(convert([" _ ",
68
+ " _|",
69
+ "|_ ",
70
+ " "]), "2")
71
+
72
+ def test_recognizes_3(self):
73
+ self.assertEqual(convert([" _ ",
74
+ " _|",
75
+ " _|",
76
+ " "]), "3")
77
+
78
+ def test_recognizes_4(self):
79
+ self.assertEqual(convert([" ",
80
+ "|_|",
81
+ " |",
82
+ " "]), "4")
83
+
84
+ def test_recognizes_5(self):
85
+ self.assertEqual(convert([" _ ",
86
+ "|_ ",
87
+ " _|",
88
+ " "]), "5")
89
+
90
+ def test_recognizes_6(self):
91
+ self.assertEqual(convert([" _ ",
92
+ "|_ ",
93
+ "|_|",
94
+ " "]), "6")
95
+
96
+ def test_recognizes_7(self):
97
+ self.assertEqual(convert([" _ ",
98
+ " |",
99
+ " |",
100
+ " "]), "7")
101
+
102
+ def test_recognizes_8(self):
103
+ self.assertEqual(convert([" _ ",
104
+ "|_|",
105
+ "|_|",
106
+ " "]), "8")
107
+
108
+ def test_recognizes_9(self):
109
+ self.assertEqual(convert([" _ ",
110
+ "|_|",
111
+ " _|",
112
+ " "]), "9")
113
+
114
+ def test_recognizes_string_of_decimal_numbers(self):
115
+ input_grid = [
116
+ " _ _ _ _ _ _ _ _ ",
117
+ " | _| _||_||_ |_ ||_||_|| |",
118
+ " ||_ _| | _||_| ||_| _||_|",
119
+ " "
120
+ ]
121
+ self.assertEqual(convert(input_grid), "1234567890")
122
+
123
+ def test_recognizes_numbers_separated_by_empty_lines(self):
124
+ input_grid = [
125
+ " _ _ ",
126
+ " | _| _|",
127
+ " ||_ _|",
128
+ " ",
129
+ " _ _ ",
130
+ "|_||_ |_ ",
131
+ " | _||_|",
132
+ " ",
133
+ " _ _ _ ",
134
+ " ||_||_|",
135
+ " ||_| _|",
136
+ " "
137
+ ]
138
+ self.assertEqual(convert(input_grid), "123,456,789")
121
139
 
122
140
 
123
141
  if __name__ == '__main__':
@@ -0,0 +1,49 @@
1
+ # Simple Linked List
2
+
3
+ Write a simple linked list implementation that uses Elements and a List.
4
+
5
+ The linked list is a fundamental data structure in computer science,
6
+ often used in the implementation of other data structures. They're
7
+ pervasive in functional programming languages, such as Clojure, Erlang,
8
+ or Haskell, but far less common in imperative languages such as Ruby or
9
+ Python.
10
+
11
+ The simplest kind of linked list is a singly linked list. Each element in the
12
+ list contains data and a "next" field pointing to the next element in the list
13
+ of elements.
14
+
15
+ This variant of linked lists is often used to represent sequences or
16
+ push-down stacks (also called a LIFO stack; Last In, First Out).
17
+
18
+ As a first take, lets create a singly linked list to contain the range (1..10),
19
+ and provide functions to reverse a linked list and convert to and from arrays.
20
+
21
+ When implementing this in a language with built-in linked lists,
22
+ implement your own abstract data type.
23
+
24
+ ## Hints
25
+
26
+ To support `list()`, see [implementing an iterator for a class.](https://docs.python.org/3/tutorial/classes.html#iterators)
27
+
28
+ Additionally, note that Python2's `next()` has been replaced by `__next__()` in Python3. For dual compatibility, `next()` can be implemented as:
29
+
30
+ ```Python
31
+ def next(self):
32
+ return self.__next__()
33
+ ```
34
+
35
+ ## Submitting Exercises
36
+
37
+ Note that, when trying to submit an exercise, make sure the solution is in the `exercism/python/<exerciseName>` directory.
38
+
39
+ For example, if you're submitting `bob.py` for the Bob exercise, the submit command would be something like `exercism submit <path_to_exercism_dir>/python/bob/bob.py`.
40
+
41
+ For more detailed information about running tests, code style and linting,
42
+ please see the [help page](http://exercism.io/languages/python).
43
+
44
+ ## Source
45
+
46
+ Inspired by 'Data Structures and Algorithms with Object-Oriented Design Patterns in Ruby', singly linked-lists. [http://www.brpreiss.com/books/opus8/html/page96.html#SECTION004300000000000000000](http://www.brpreiss.com/books/opus8/html/page96.html#SECTION004300000000000000000)
47
+
48
+ ## Submitting Incomplete Solutions
49
+ It's possible to submit an incomplete solution so you can see how others have completed the exercise.