trackler 2.2.1.62 → 2.2.1.63

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 (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.