trackler 2.1.0.9 → 2.1.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (230) hide show
  1. checksums.yaml +4 -4
  2. data/common/exercises/perfect-numbers/description.md +2 -2
  3. data/common/exercises/phone-number/canonical-data.json +1 -7
  4. data/common/exercises/tournament/canonical-data.json +96 -21
  5. data/common/exercises/tournament/description.md +0 -5
  6. data/lib/trackler/version.rb +1 -1
  7. data/tracks/coq/README.md +6 -8
  8. data/tracks/coq/exercises/hello-world/example.v +3 -0
  9. data/tracks/coq/exercises/hello-world/hello-world.v +3 -0
  10. data/tracks/coq/exercises/rna-transcription/DNA.v +4 -0
  11. data/tracks/coq/exercises/rna-transcription/example.v +15 -0
  12. data/tracks/coq/exercises/rna-transcription/rna-transcription.v +5 -0
  13. data/tracks/coq/exercises/tautology/description.md +1 -0
  14. data/tracks/coq/exercises/tautology/example.v +4 -0
  15. data/tracks/coq/exercises/tautology/tautology.v +4 -0
  16. data/tracks/haskell/exercises/accumulate/package.yaml +1 -0
  17. data/tracks/haskell/exercises/accumulate/test/Tests.hs +0 -3
  18. data/tracks/haskell/exercises/acronym/package.yaml +1 -0
  19. data/tracks/haskell/exercises/acronym/test/Tests.hs +0 -5
  20. data/tracks/haskell/exercises/all-your-base/package.yaml +1 -0
  21. data/tracks/haskell/exercises/all-your-base/test/Tests.hs +0 -2
  22. data/tracks/haskell/exercises/allergies/package.yaml +1 -0
  23. data/tracks/haskell/exercises/allergies/test/Tests.hs +0 -2
  24. data/tracks/haskell/exercises/alphametics/package.yaml +1 -0
  25. data/tracks/haskell/exercises/alphametics/test/Tests.hs +0 -2
  26. data/tracks/haskell/exercises/anagram/package.yaml +1 -0
  27. data/tracks/haskell/exercises/anagram/test/Tests.hs +0 -2
  28. data/tracks/haskell/exercises/atbash-cipher/package.yaml +1 -0
  29. data/tracks/haskell/exercises/atbash-cipher/test/Tests.hs +0 -2
  30. data/tracks/haskell/exercises/bank-account/package.yaml +1 -0
  31. data/tracks/haskell/exercises/bank-account/test/Tests.hs +0 -3
  32. data/tracks/haskell/exercises/beer-song/package.yaml +1 -0
  33. data/tracks/haskell/exercises/binary/package.yaml +1 -0
  34. data/tracks/haskell/exercises/binary/test/Tests.hs +0 -1
  35. data/tracks/haskell/exercises/binary-search-tree/package.yaml +1 -0
  36. data/tracks/haskell/exercises/binary-search-tree/test/Tests.hs +0 -3
  37. data/tracks/haskell/exercises/bob/package.yaml +1 -0
  38. data/tracks/haskell/exercises/bob/test/Tests.hs +0 -2
  39. data/tracks/haskell/exercises/bowling/package.yaml +1 -0
  40. data/tracks/haskell/exercises/bowling/test/Tests.hs +0 -2
  41. data/tracks/haskell/exercises/bracket-push/package.yaml +1 -0
  42. data/tracks/haskell/exercises/bracket-push/test/Tests.hs +1 -6
  43. data/tracks/haskell/exercises/change/package.yaml +1 -0
  44. data/tracks/haskell/exercises/change/test/Tests.hs +0 -2
  45. data/tracks/haskell/exercises/clock/package.yaml +1 -0
  46. data/tracks/haskell/exercises/clock/test/Tests.hs +0 -2
  47. data/tracks/haskell/exercises/connect/package.yaml +1 -0
  48. data/tracks/haskell/exercises/connect/test/Tests.hs +0 -2
  49. data/tracks/haskell/exercises/crypto-square/package.yaml +1 -0
  50. data/tracks/haskell/exercises/crypto-square/test/Tests.hs +0 -2
  51. data/tracks/haskell/exercises/custom-set/package.yaml +1 -0
  52. data/tracks/haskell/exercises/custom-set/test/Tests.hs +0 -3
  53. data/tracks/haskell/exercises/difference-of-squares/package.yaml +1 -0
  54. data/tracks/haskell/exercises/difference-of-squares/test/Tests.hs +0 -3
  55. data/tracks/haskell/exercises/dominoes/package.yaml +1 -0
  56. data/tracks/haskell/exercises/dominoes/test/Tests.hs +0 -2
  57. data/tracks/haskell/exercises/etl/package.yaml +1 -0
  58. data/tracks/haskell/exercises/etl/test/Tests.hs +0 -2
  59. data/tracks/haskell/exercises/food-chain/package.yaml +1 -0
  60. data/tracks/haskell/exercises/forth/package.yaml +1 -0
  61. data/tracks/haskell/exercises/forth/test/Tests.hs +0 -2
  62. data/tracks/haskell/exercises/gigasecond/package.yaml +1 -0
  63. data/tracks/haskell/exercises/gigasecond/test/Tests.hs +0 -3
  64. data/tracks/haskell/exercises/go-counting/package.yaml +1 -0
  65. data/tracks/haskell/exercises/go-counting/test/Tests.hs +0 -3
  66. data/tracks/haskell/exercises/grade-school/package.yaml +1 -0
  67. data/tracks/haskell/exercises/grade-school/test/Tests.hs +0 -3
  68. data/tracks/haskell/exercises/grains/package.yaml +1 -0
  69. data/tracks/haskell/exercises/grains/test/Tests.hs +0 -2
  70. data/tracks/haskell/exercises/hamming/package.yaml +1 -0
  71. data/tracks/haskell/exercises/hamming/test/Tests.hs +0 -2
  72. data/tracks/haskell/exercises/hello-world/package.yaml +1 -0
  73. data/tracks/haskell/exercises/hexadecimal/package.yaml +1 -0
  74. data/tracks/haskell/exercises/hexadecimal/test/Tests.hs +0 -3
  75. data/tracks/haskell/exercises/house/package.yaml +1 -0
  76. data/tracks/haskell/exercises/kindergarten-garden/package.yaml +1 -0
  77. data/tracks/haskell/exercises/kindergarten-garden/test/Tests.hs +0 -3
  78. data/tracks/haskell/exercises/largest-series-product/package.yaml +1 -0
  79. data/tracks/haskell/exercises/largest-series-product/test/Tests.hs +0 -3
  80. data/tracks/haskell/exercises/leap/package.yaml +1 -0
  81. data/tracks/haskell/exercises/leap/test/Tests.hs +0 -2
  82. data/tracks/haskell/exercises/lens-person/package.yaml +1 -0
  83. data/tracks/haskell/exercises/lens-person/test/Tests.hs +0 -3
  84. data/tracks/haskell/exercises/linked-list/package.yaml +1 -0
  85. data/tracks/haskell/exercises/linked-list/test/Tests.hs +0 -3
  86. data/tracks/haskell/exercises/list-ops/package.yaml +1 -0
  87. data/tracks/haskell/exercises/list-ops/test/Tests.hs +0 -3
  88. data/tracks/haskell/exercises/luhn/package.yaml +1 -0
  89. data/tracks/haskell/exercises/luhn/test/Tests.hs +0 -3
  90. data/tracks/haskell/exercises/matrix/package.yaml +1 -0
  91. data/tracks/haskell/exercises/matrix/test/Tests.hs +0 -3
  92. data/tracks/haskell/exercises/meetup/package.yaml +1 -0
  93. data/tracks/haskell/exercises/meetup/test/Tests.hs +0 -2
  94. data/tracks/haskell/exercises/minesweeper/package.yaml +1 -0
  95. data/tracks/haskell/exercises/minesweeper/test/Tests.hs +0 -3
  96. data/tracks/haskell/exercises/nth-prime/package.yaml +1 -0
  97. data/tracks/haskell/exercises/nth-prime/test/Tests.hs +0 -2
  98. data/tracks/haskell/exercises/nucleotide-count/package.yaml +1 -0
  99. data/tracks/haskell/exercises/nucleotide-count/test/Tests.hs +0 -2
  100. data/tracks/haskell/exercises/ocr-numbers/package.yaml +1 -0
  101. data/tracks/haskell/exercises/ocr-numbers/test/Tests.hs +0 -3
  102. data/tracks/haskell/exercises/octal/package.yaml +1 -0
  103. data/tracks/haskell/exercises/octal/test/Tests.hs +0 -3
  104. data/tracks/haskell/exercises/palindrome-products/package.yaml +1 -0
  105. data/tracks/haskell/exercises/palindrome-products/test/Tests.hs +0 -3
  106. data/tracks/haskell/exercises/pangram/package.yaml +1 -0
  107. data/tracks/haskell/exercises/pangram/test/Tests.hs +0 -5
  108. data/tracks/haskell/exercises/parallel-letter-frequency/package.yaml +1 -0
  109. data/tracks/haskell/exercises/parallel-letter-frequency/test/Tests.hs +0 -3
  110. data/tracks/haskell/exercises/pascals-triangle/package.yaml +1 -0
  111. data/tracks/haskell/exercises/pascals-triangle/test/Tests.hs +0 -2
  112. data/tracks/haskell/exercises/phone-number/package.yaml +1 -0
  113. data/tracks/haskell/exercises/phone-number/test/Tests.hs +0 -2
  114. data/tracks/haskell/exercises/pig-latin/package.yaml +1 -0
  115. data/tracks/haskell/exercises/pig-latin/test/Tests.hs +0 -2
  116. data/tracks/haskell/exercises/pov/package.yaml +1 -0
  117. data/tracks/haskell/exercises/pov/test/Tests.hs +0 -2
  118. data/tracks/haskell/exercises/prime-factors/package.yaml +1 -0
  119. data/tracks/haskell/exercises/prime-factors/test/Tests.hs +0 -2
  120. data/tracks/haskell/exercises/pythagorean-triplet/package.yaml +1 -0
  121. data/tracks/haskell/exercises/pythagorean-triplet/test/Tests.hs +0 -3
  122. data/tracks/haskell/exercises/queen-attack/package.yaml +1 -0
  123. data/tracks/haskell/exercises/queen-attack/test/Tests.hs +0 -2
  124. data/tracks/haskell/exercises/raindrops/package.yaml +1 -0
  125. data/tracks/haskell/exercises/raindrops/test/Tests.hs +0 -2
  126. data/tracks/haskell/exercises/rna-transcription/package.yaml +1 -0
  127. data/tracks/haskell/exercises/rna-transcription/test/Tests.hs +0 -2
  128. data/tracks/haskell/exercises/robot-name/package.yaml +1 -0
  129. data/tracks/haskell/exercises/robot-name/test/Tests.hs +0 -3
  130. data/tracks/haskell/exercises/robot-simulator/package.yaml +1 -0
  131. data/tracks/haskell/exercises/robot-simulator/test/Tests.hs +0 -3
  132. data/tracks/haskell/exercises/roman-numerals/package.yaml +1 -0
  133. data/tracks/haskell/exercises/roman-numerals/test/Tests.hs +0 -2
  134. data/tracks/haskell/exercises/run-length-encoding/package.yaml +1 -0
  135. data/tracks/haskell/exercises/run-length-encoding/test/Tests.hs +0 -4
  136. data/tracks/haskell/exercises/saddle-points/package.yaml +1 -0
  137. data/tracks/haskell/exercises/saddle-points/test/Tests.hs +0 -3
  138. data/tracks/haskell/exercises/say/package.yaml +1 -0
  139. data/tracks/haskell/exercises/say/test/Tests.hs +0 -2
  140. data/tracks/haskell/exercises/scrabble-score/package.yaml +1 -0
  141. data/tracks/haskell/exercises/scrabble-score/test/Tests.hs +0 -2
  142. data/tracks/haskell/exercises/secret-handshake/package.yaml +1 -0
  143. data/tracks/haskell/exercises/secret-handshake/test/Tests.hs +0 -2
  144. data/tracks/haskell/exercises/series/package.yaml +1 -0
  145. data/tracks/haskell/exercises/series/test/Tests.hs +0 -3
  146. data/tracks/haskell/exercises/sgf-parsing/package.yaml +1 -0
  147. data/tracks/haskell/exercises/sgf-parsing/test/Tests.hs +0 -3
  148. data/tracks/haskell/exercises/sieve/package.yaml +1 -0
  149. data/tracks/haskell/exercises/sieve/test/Tests.hs +0 -2
  150. data/tracks/haskell/exercises/simple-cipher/package.yaml +1 -0
  151. data/tracks/haskell/exercises/simple-cipher/test/Tests.hs +0 -3
  152. data/tracks/haskell/exercises/simple-linked-list/package.yaml +1 -0
  153. data/tracks/haskell/exercises/simple-linked-list/test/Tests.hs +0 -3
  154. data/tracks/haskell/exercises/space-age/package.yaml +1 -0
  155. data/tracks/haskell/exercises/space-age/test/Tests.hs +0 -2
  156. data/tracks/haskell/exercises/strain/package.yaml +1 -0
  157. data/tracks/haskell/exercises/strain/test/Tests.hs +0 -3
  158. data/tracks/haskell/exercises/sublist/package.yaml +1 -0
  159. data/tracks/haskell/exercises/sublist/test/Tests.hs +0 -2
  160. data/tracks/haskell/exercises/sum-of-multiples/package.yaml +1 -0
  161. data/tracks/haskell/exercises/sum-of-multiples/test/Tests.hs +0 -2
  162. data/tracks/haskell/exercises/triangle/package.yaml +1 -0
  163. data/tracks/haskell/exercises/triangle/test/Tests.hs +0 -3
  164. data/tracks/haskell/exercises/trinary/package.yaml +1 -0
  165. data/tracks/haskell/exercises/trinary/test/Tests.hs +0 -3
  166. data/tracks/haskell/exercises/word-count/package.yaml +1 -0
  167. data/tracks/haskell/exercises/word-count/test/Tests.hs +0 -2
  168. data/tracks/haskell/exercises/wordy/package.yaml +1 -0
  169. data/tracks/haskell/exercises/wordy/test/Tests.hs +0 -2
  170. data/tracks/haskell/exercises/zebra-puzzle/package.yaml +1 -0
  171. data/tracks/haskell/exercises/zipper/package.yaml +1 -0
  172. data/tracks/haskell/exercises/zipper/test/Tests.hs +0 -3
  173. data/tracks/java/exercises/book-store/src/test/java/BookstoreTest.java +12 -12
  174. data/tracks/java/exercises/ocr-numbers/src/test/java/OpticalCharacterReaderTest.java +16 -16
  175. data/tracks/java/exercises/strain/src/test/java/StrainTest.java +11 -11
  176. data/tracks/perl6/README.md +12 -0
  177. data/tracks/perl6/bin/README.md +3 -0
  178. data/tracks/perl6/config.json +20 -20
  179. data/tracks/perl6/exercises/accumulate/{Example.pm → Example.pm6} +0 -0
  180. data/tracks/perl6/exercises/all-your-base/{Example.pm → Example.pm6} +0 -0
  181. data/tracks/perl6/exercises/allergies/{Example.pm → Example.pm6} +0 -0
  182. data/tracks/perl6/exercises/anagram/{Example.pm → Example.pm6} +0 -0
  183. data/tracks/perl6/exercises/atbash-cipher/{Example.pm → Example.pm6} +0 -0
  184. data/tracks/perl6/exercises/binary/{Example.pm → Example.pm6} +0 -0
  185. data/tracks/perl6/exercises/bob/{Example.pm → Example.pm6} +0 -0
  186. data/tracks/perl6/exercises/bob/bob.t +181 -180
  187. data/tracks/perl6/exercises/bob/example.yaml +1 -0
  188. data/tracks/perl6/exercises/grade-school/{Example.pm → Example.pm6} +0 -0
  189. data/tracks/perl6/exercises/grade-school/grade-school.t +9 -18
  190. data/tracks/perl6/exercises/grains/{Example.pm → Example.pm6} +0 -0
  191. data/tracks/perl6/exercises/hello-world/{Example.pm → Example.pm6} +0 -0
  192. data/tracks/perl6/exercises/hello-world/example.yaml +1 -0
  193. data/tracks/perl6/exercises/hello-world/hello-world.t +38 -43
  194. data/tracks/perl6/exercises/leap/{Example.pm → Example.pm6} +0 -0
  195. data/tracks/perl6/exercises/leap/leap.t +40 -42
  196. data/tracks/perl6/exercises/phone-number/{Example.pm → Example.pm6} +2 -2
  197. data/tracks/perl6/exercises/phone-number/PhoneNumber.pm6 +1 -1
  198. data/tracks/perl6/exercises/phone-number/example.yaml +2 -2
  199. data/tracks/perl6/exercises/phone-number/phone-number.t +3 -9
  200. data/tracks/perl6/exercises/raindrops/{Example.pm → Example.pm6} +0 -0
  201. data/tracks/perl6/exercises/rna-transcription/{Example.pm → Example.pm6} +0 -0
  202. data/tracks/perl6/exercises/robot-name/{Example.pm → Example.pm6} +0 -0
  203. data/tracks/perl6/exercises/scrabble-score/{Example.pm → Example.pm6} +0 -0
  204. data/tracks/perl6/exercises/space-age/{Example.pm → Example.pm6} +0 -0
  205. data/tracks/perl6/exercises/trinary/{Example.pm → Example.pm6} +0 -0
  206. data/tracks/perl6/exercises/word-count/{Example.pm → Example.pm6} +0 -0
  207. data/tracks/perl6/exercises/wordy/{Example.pm → Example.pm6} +0 -0
  208. data/tracks/python/.github/stale.yml +4 -4
  209. data/tracks/python/config.json +24 -0
  210. data/tracks/python/exercises/alphametics/alphametics.py +2 -0
  211. data/tracks/python/exercises/alphametics/alphametics_test.py +71 -0
  212. data/tracks/python/exercises/alphametics/example.py +29 -0
  213. data/tracks/python/exercises/book-store/book_store.py +2 -0
  214. data/tracks/python/exercises/book-store/book_store_test.py +72 -0
  215. data/tracks/python/exercises/book-store/example.py +29 -0
  216. data/tracks/python/exercises/meetup/meetup_test.py +341 -1
  217. data/tracks/python/exercises/tournament/example.py +45 -0
  218. data/tracks/python/exercises/tournament/tournament.py +2 -0
  219. data/tracks/python/exercises/tournament/tournament_test.py +70 -0
  220. data/tracks/python/exercises/variable-length-quantity/example.py +34 -0
  221. data/tracks/python/exercises/variable-length-quantity/variable_length_quantity.py +6 -0
  222. data/tracks/python/exercises/variable-length-quantity/variable_length_quantity_test.py +100 -0
  223. data/tracks/r/config.json +23 -23
  224. data/tracks/r/exercises/perfect-numbers/test_perfect-numbers.R +1 -1
  225. data/tracks/r/exercises/prime-factors/test_prime-factors.R +2 -0
  226. data/tracks/r/exercises/tournament/example.R +2 -5
  227. data/tracks/scala/exercises/leap/example.scala +4 -4
  228. data/tracks/scala/exercises/leap/src/main/scala/Leap.scala +3 -0
  229. data/tracks/scala/exercises/leap/src/test/scala/LeapTest.scala +6 -6
  230. metadata +43 -22
@@ -10,6 +10,7 @@ tests: |
10
10
  exercise_comment: The name of this exercise.
11
11
  module_comment: "%*ENV<EXERCISM> is for tests not directly for the exercise, don't worry about these :)"
12
12
  version_comment: The version we will be matching against the exercise.
13
+ lib_comment: Look for the module inside the same directory as this test file.
13
14
  plan_comment: This is how many tests we expect to run.
14
15
  use_test_comment: Check that the module can be use-d.
15
16
  version_test_comment: "If the exercise is updated, we want to make sure other people testing\nyour code don't think you've made a mistake if things have changed!"
@@ -6,10 +6,11 @@ use lib $?FILE.IO.dirname;
6
6
  my $exercise = 'GradeSchool';
7
7
  my $version = v1;
8
8
  my $module = %*ENV<EXERCISM> ?? 'Example' !! $exercise;
9
- plan 11;
9
+ plan 10;
10
10
 
11
11
  use-ok $module or bail-out;
12
12
  require ::($module);
13
+
13
14
  if ::($exercise).^ver !~~ $version {
14
15
  warn "\nExercise version mismatch. Further tests may fail!"
15
16
  ~ "\n$exercise is $(::($exercise).^ver.gist). "
@@ -17,35 +18,25 @@ if ::($exercise).^ver !~~ $version {
17
18
  bail-out 'Example version must match test version.' if %*ENV<EXERCISM>;
18
19
  }
19
20
 
20
- my @classes;
21
- BEGIN { @classes = <Roster> };
22
- subtest 'Class(es)', {
23
- plan 1;
24
- eval-lives-ok "use $module; ::('$_').new or die 'Could not use .new method on class $_.\'", $_ for @classes;
25
- } or bail-out 'All classes must be defined and exported.';
26
- require ::($module) @classes.eager;
21
+ require ::($module) <Roster>;
27
22
 
28
- for @classes -> $class {
29
- subtest "$class class method(s)", {
30
- plan 3;
31
- ok ::($class).can($_), $_ for <add-student list-grade list-all>;
32
- }
23
+ subtest "Roster class methods", {
24
+ plan 3;
25
+ ok ::('Roster').can($_), $_ for <add-student list-grade list-all>;
33
26
  }
34
-
35
- my $roster = Roster.new;
36
-
27
+ my $roster = ::('Roster').new;
37
28
  ok $roster.?add-student(:name('Jim'), :2grade), 'Add Jim to grade 2';
38
29
  is $roster.?list-grade(2), <Jim>, 'List grade 2';
39
30
  ok $roster.?add-student(:name('Zoe'), :2grade), 'Add Zoe to grade 2';
40
31
  ok $roster.?add-student(:name('Barb'), :1grade), 'Add Barb to grade 1';
41
32
  is $roster.?list-grade(2), <Jim Zoe>, 'List grade 2';
42
33
  is $roster.?list-grade(1), <Barb>, 'List grade 1';
43
-
44
34
  subtest 'Additional students', {
45
35
  plan 6;
46
36
  ok $roster.?add-student(:name($_), :1grade), "Add $_ to grade 1" for <Charlie Anna>;
47
37
  ok $roster.?add-student(:name('Alex'), :2grade), 'Add Alex to grade 2';
48
38
  ok $roster.?add-student(:name($_), :3grade), "Add $_ to grade 3" for <Tom Dick Harry>;
49
39
  }
50
-
51
40
  is $roster.?list-all, ('Grade 1', <Anna Barb Charlie>, 'Grade 2', <Alex Jim Zoe>, 'Grade 3', <Dick Harry Tom>), 'List all';
41
+
42
+ done-testing;
@@ -10,6 +10,7 @@ tests: |
10
10
  exercise_comment: The name of this exercise.
11
11
  module_comment: "%*ENV<EXERCISM> is for tests not directly for the exercise, don't worry about these :)"
12
12
  version_comment: The version we will be matching against the exercise.
13
+ lib_comment: Look for the module inside the same directory as this test file.
13
14
  plan_comment: This is how many tests we expect to run.
14
15
  use_test_comment: Check that the module can be use-d.
15
16
  version_test_comment: "If the exercise is updated, we want to make sure other people testing\nyour code don't think you've made a mistake if things have changed!"
@@ -1,20 +1,20 @@
1
1
  #!/usr/bin/env perl6
2
2
  use v6;
3
3
  use Test;
4
- use lib my $dir = $?FILE.IO.dirname; # Look for the module inside the same directory as this test file.
4
+ use lib my $dir = $?FILE.IO.dirname; #`[Look for the module inside the same directory as this test file.]
5
5
  use JSON::Tiny;
6
6
 
7
- my $exercise = 'HelloWorld'; # The name of this exercise.
8
- my $version = v2; # The version we will be matching against the exercise.
9
- my $module = %*ENV<EXERCISM> ?? 'Example' !! $exercise; # %*ENV<EXERCISM> is for tests not directly for the exercise, don't worry about these :)
10
- plan 4; # This is how many tests we expect to run.
7
+ my $exercise = 'HelloWorld'; #`[The name of this exercise.]
8
+ my $version = v2; #`[The version we will be matching against the exercise.]
9
+ my $module = %*ENV<EXERCISM> ?? 'Example' !! $exercise; #`[%*ENV<EXERCISM> is for tests not directly for the exercise, don't worry about these :)]
10
+ plan 3; #`[This is how many tests we expect to run.]
11
11
 
12
- # Check that the module can be use-d.
12
+ #`[Check that the module can be use-d.]
13
13
  use-ok $module or bail-out;
14
14
  require ::($module);
15
15
 
16
- # If the exercise is updated, we want to make sure other people testing
17
- # your code don't think you've made a mistake if things have changed!
16
+ #`[If the exercise is updated, we want to make sure other people testing
17
+ your code don't think you've made a mistake if things have changed!]
18
18
  if ::($exercise).^ver !~~ $version {
19
19
  warn "\nExercise version mismatch. Further tests may fail!"
20
20
  ~ "\n$exercise is $(::($exercise).^ver.gist). "
@@ -22,42 +22,37 @@ if ::($exercise).^ver !~~ $version {
22
22
  bail-out 'Example version must match test version.' if %*ENV<EXERCISM>;
23
23
  }
24
24
 
25
- # Check that the Module 'HelloWorld' can use all of the subroutines
26
- # needed in the tests (only '&hello' for this one).
27
- my @subs;
28
- BEGIN { @subs = <&hello> };
29
- subtest 'Subroutine(s)', {
30
- plan 1;
31
- eval-lives-ok "use $module; ::('$_').defined or die '$_ is not defined.'", $_ for @subs;
32
- } or bail-out 'All subroutines must be defined and exported.';
33
- require ::($module) @subs.eager;
34
-
35
- # Go through the cases (hiding at the bottom of this file)
36
- # and check that &hello gives us the correct response.
37
- is hello, |.<expected description> for @(my $c-data.<cases>);
38
-
39
- # Ignore this for your exercise! Tells Exercism folks when exercise cases become out of date.
40
- if %*ENV<EXERCISM> && (my $c-data-file = "$dir/../../x-common/exercises/{$dir.IO.basename}/canonical-data.json".IO.resolve) ~~ :f {
41
- is $c-data, from-json($c-data-file.slurp), 'canonical-data'
42
- } else { skip }
43
-
44
- # There are no more tests after this :)
45
- done-testing;
46
-
47
- # 'INIT' is a phaser, it makes sure that the test data is available before everything else
48
- # starts running (otherwise we'd have to shove the test data into the middle of the file!)
25
+ #`[Import '&hello' from 'HelloWorld']
26
+ require ::($module) <&hello>;
27
+
28
+ my $c-data;
29
+ #`[Go through the cases (hiding at the bottom of this file)
30
+ and check that &hello gives us the correct response.]
31
+ is &::('hello')(), |.<expected description> for @($c-data<cases>);
32
+
33
+ #`[Ignore this for your exercise! Tells Exercism folks when exercise cases become out of date.]
34
+ if %*ENV<EXERCISM> && (my $c-data-file =
35
+ "$dir/../../x-common/exercises/{$dir.IO.resolve.basename}/canonical-data.json".IO.resolve) ~~ :f
36
+ { is-deeply $c-data, from-json($c-data-file.slurp), 'canonical-data' } else { skip }
37
+
38
+ done-testing; #`[There are no more tests after this :)]
39
+
40
+ #`['INIT' is a phaser, it makes sure that the test data is available before everything else
41
+ starts running (otherwise we'd have to shove the test data into the middle of the file!)]
49
42
  INIT {
50
- $c-data := from-json
43
+ $c-data := from-json q:to/END/;
44
+
45
+ {
46
+ "exercise": "hello-world",
47
+ "version": "1.0.0",
48
+ "cases": [
51
49
  {
52
- "exercise": "hello-world",
53
- "version": "1.0.0",
54
- "cases": [
55
- {
56
- "description": "Say Hi!",
57
- "property": "hello",
58
- "expected": "Hello, World!"
59
- }
60
- ]
50
+ "description": "Say Hi!",
51
+ "property": "hello",
52
+ "expected": "Hello, World!"
61
53
  }
62
-
54
+ ]
55
+ }
56
+
57
+ END
63
58
  }
@@ -7,10 +7,11 @@ use JSON::Tiny;
7
7
  my $exercise = 'Leap';
8
8
  my $version = v1;
9
9
  my $module = %*ENV<EXERCISM> ?? 'Example' !! $exercise;
10
- plan 7;
10
+ plan 6;
11
11
 
12
12
  use-ok $module or bail-out;
13
13
  require ::($module);
14
+
14
15
  if ::($exercise).^ver !~~ $version {
15
16
  warn "\nExercise version mismatch. Further tests may fail!"
16
17
  ~ "\n$exercise is $(::($exercise).^ver.gist). "
@@ -18,53 +19,50 @@ if ::($exercise).^ver !~~ $version {
18
19
  bail-out 'Example version must match test version.' if %*ENV<EXERCISM>;
19
20
  }
20
21
 
21
- my @subs;
22
- BEGIN { @subs = <&is-leap-year> };
23
- subtest 'Subroutine(s)', {
24
- plan 1;
25
- eval-lives-ok "use $module; ::('$_').defined or die '$_ is not defined.'", $_ for @subs;
26
- } or bail-out 'All subroutines must be defined and exported.';
27
- require ::($module) @subs.eager;
22
+ require ::($module) <&is-leap-year>;
28
23
 
29
- is .<input>.&is-leap-year, |.<expected description> for @(my $c-data.<cases>);
24
+ my $c-data;
25
+ is &::('is-leap-year')(.<input>), |.<expected description> for @($c-data<cases>);
30
26
 
31
- if %*ENV<EXERCISM> && (my $c-data-file = "$dir/../../x-common/exercises/{$dir.IO.basename}/canonical-data.json".IO.resolve) ~~ :f {
32
- is-deeply $c-data, from-json($c-data-file.slurp), 'canonical-data'
33
- } else { skip }
27
+ if %*ENV<EXERCISM> && (my $c-data-file =
28
+ "$dir/../../x-common/exercises/{$dir.IO.resolve.basename}/canonical-data.json".IO.resolve) ~~ :f
29
+ { is-deeply $c-data, from-json($c-data-file.slurp), 'canonical-data' } else { skip }
34
30
 
35
31
  done-testing;
36
32
 
37
33
  INIT {
38
- $c-data := from-json
34
+ $c-data := from-json q:to/END/;
35
+
36
+ {
37
+ "exercise": "leap",
38
+ "version": "1.0.0",
39
+ "cases": [
40
+ {
41
+ "description": "year not divisible by 4: common year",
42
+ "property": "leapYear",
43
+ "input": 2015,
44
+ "expected": false
45
+ },
46
+ {
47
+ "description": "year divisible by 4, not divisible by 100: leap year",
48
+ "property": "leapYear",
49
+ "input": 2016,
50
+ "expected": true
51
+ },
39
52
  {
40
- "exercise": "leap",
41
- "version": "1.0.0",
42
- "cases": [
43
- {
44
- "description": "year not divisible by 4: common year",
45
- "property": "leapYear",
46
- "input": 2015,
47
- "expected": false
48
- },
49
- {
50
- "description": "year divisible by 4, not divisible by 100: leap year",
51
- "property": "leapYear",
52
- "input": 2016,
53
- "expected": true
54
- },
55
- {
56
- "description": "year divisible by 100, not divisible by 400: common year",
57
- "property": "leapYear",
58
- "input": 2100,
59
- "expected": false
60
- },
61
- {
62
- "description": "year divisible by 400: leap year",
63
- "property": "leapYear",
64
- "input": 2000,
65
- "expected": true
66
- }
67
- ]
53
+ "description": "year divisible by 100, not divisible by 400: common year",
54
+ "property": "leapYear",
55
+ "input": 2100,
56
+ "expected": false
57
+ },
58
+ {
59
+ "description": "year divisible by 400: leap year",
60
+ "property": "leapYear",
61
+ "input": 2000,
62
+ "expected": true
68
63
  }
69
-
64
+ ]
65
+ }
66
+
67
+ END
70
68
  }
@@ -1,6 +1,6 @@
1
- unit module Phone:ver<2>;
1
+ unit module Phone:ver<3>;
2
2
 
3
3
  sub clean-number ($number is copy) is export {
4
- $number ~~ /<:L>/ ?? return Nil !! $number ~~ s:g/<:!Nd>//;
4
+ $number ~~ s:g/<:!Nd>//;
5
5
  $number ~~ /^ 1? ( [ <[2..9]> <:Nd> ** 2 ] ** 2 <:Nd> ** 4 ) $/ ?? ~$0 !! Nil;
6
6
  }
@@ -1,4 +1,4 @@
1
- unit module Phone:ver<2>;
1
+ unit module Phone:ver<3>;
2
2
 
3
3
  sub clean-number ($number) is export {
4
4
  }
@@ -1,6 +1,6 @@
1
1
  exercise: Phone
2
- version: 2
3
- plan: 15
2
+ version: 3
3
+ plan: 14
4
4
  imports: '&clean-number'
5
5
  tests: |
6
6
  for @($c-data<cases>[0]<cases>) {
@@ -5,9 +5,9 @@ use lib my $dir = $?FILE.IO.dirname;
5
5
  use JSON::Tiny;
6
6
 
7
7
  my $exercise = 'Phone';
8
- my $version = v2;
8
+ my $version = v3;
9
9
  my $module = %*ENV<EXERCISM> ?? 'Example' !! $exercise;
10
- plan 15;
10
+ plan 14;
11
11
 
12
12
  use-ok $module or bail-out;
13
13
  require ::($module);
@@ -41,7 +41,7 @@ $c-data := from-json q:to/END/;
41
41
 
42
42
  {
43
43
  "exercise": "phone-number",
44
- "version": "1.1.0",
44
+ "version": "1.2.0",
45
45
  "cases": [
46
46
  {
47
47
  "description": "Cleanup user-entered phone numbers",
@@ -111,12 +111,6 @@ $c-data := from-json q:to/END/;
111
111
  "phrase": "123-@:!-7890",
112
112
  "expected": null
113
113
  },
114
- {
115
- "description": "invalid with right number of digits but letters mixed in",
116
- "property": "clean",
117
- "phrase": "1a2b3c4d5e6f7g8h9i0j",
118
- "expected": null
119
- },
120
114
  {
121
115
  "description": "invalid if area code does not start with 2-9",
122
116
  "property": "clean",
@@ -1,17 +1,17 @@
1
1
  # Number of days of inactivity before an issue becomes stale
2
- daysUntilStale: 21
2
+ daysUntilStale: 60
3
3
  # Number of days of inactivity before a stale issue is closed
4
4
  daysUntilClose: 7
5
5
  # Issues with these labels will never be considered stale
6
6
  exemptLabels:
7
+ - discussion
7
8
  - pinned
8
- - security
9
9
  # Label to use when marking an issue as stale
10
10
  staleLabel: on hiatus
11
11
  # Comment to post when marking an issue as stale. Set to `false` to disable
12
12
  markComment: >
13
- This issue has been automatically marked as `on hiatus because it has not had
13
+ This issue has been automatically marked as `on hiatus` because it has not had
14
14
  recent activity. It will be closed if no further activity occurs. Thank you
15
15
  for your contributions.
16
16
  # Comment to post when closing a stale issue. Set to `false` to disable
17
- closeComment: false
17
+ closeComment: false
@@ -416,6 +416,12 @@
416
416
  "topics": [
417
417
  ]
418
418
  },
419
+ {
420
+ "slug": "book-store",
421
+ "difficulty": 1,
422
+ "topics": [
423
+ ]
424
+ },
419
425
  {
420
426
  "slug": "linked-list",
421
427
  "difficulty": 1,
@@ -428,6 +434,12 @@
428
434
  "topics": [
429
435
  ]
430
436
  },
437
+ {
438
+ "slug": "variable-length-quantity",
439
+ "difficulty": 1,
440
+ "topics": [
441
+ ]
442
+ },
431
443
  {
432
444
  "slug": "all-your-base",
433
445
  "difficulty": 4,
@@ -463,6 +475,18 @@
463
475
  "strings",
464
476
  "searching"
465
477
  ]
478
+ },
479
+ {
480
+ "slug": "alphametics",
481
+ "difficulty": 6,
482
+ "topics": [
483
+ ]
484
+ },
485
+ {
486
+ "slug": "tournament",
487
+ "difficulty": 1,
488
+ "topics": [
489
+ ]
466
490
  }
467
491
  ],
468
492
  "deprecated": [
@@ -0,0 +1,2 @@
1
+ def solve():
2
+ pass
@@ -0,0 +1,71 @@
1
+ import unittest
2
+
3
+ from alphametics import solve
4
+
5
+
6
+ # test cases adapted from `x-common//canonical-data.json` @ version: 1.0.0
7
+
8
+ class TestAlphametics(unittest.TestCase):
9
+ def test_puzzle_with_three_letters(self):
10
+ self.assertEqual(solve("I + BB == ILL"), {"I": 1, "B": 9, "L": 0})
11
+
12
+ def solution_must_have_unique_value_for_each_letter(self):
13
+ self.assertEqual(solve("A == B"), {})
14
+
15
+ def leading_zero_solution_is_invalid(self):
16
+ self.assertEqual(solve("ACA + DD == BD"), {})
17
+
18
+ def test_puzzle_with_four_letters(self):
19
+ self.assertEqual(
20
+ solve("AS + A == MOM"), {"A": 9, "S": 2, "M": 1, "O": 0})
21
+
22
+ def puzzle_with_six_letters(self):
23
+ self.assertEqual(
24
+ solve("NO + NO + TOO == LATE"),
25
+ {"N": 7,
26
+ "O": 4,
27
+ "T": 9,
28
+ "L": 1,
29
+ "A": 0,
30
+ "E": 2})
31
+
32
+ def test_puzzle_with_seven_letters(self):
33
+ self.assertEqual(
34
+ solve("HE + SEES + THE == LIGHT"),
35
+ {"E": 4,
36
+ "G": 2,
37
+ "H": 5,
38
+ "I": 0,
39
+ "L": 1,
40
+ "S": 9,
41
+ "T": 7})
42
+
43
+ def test_puzzle_with_eight_letters(self):
44
+ self.assertEqual(
45
+ solve("SEND + MORE == MONEY"),
46
+ {"S": 9,
47
+ "E": 5,
48
+ "N": 6,
49
+ "D": 7,
50
+ "M": 1,
51
+ "O": 0,
52
+ "R": 8,
53
+ "Y": 2})
54
+
55
+ def test_puzzle_with_ten_letters(self):
56
+ self.assertEqual(
57
+ solve("AND + A + STRONG + OFFENSE + AS + A + GOOD == DEFENSE"),
58
+ {"A": 5,
59
+ "D": 3,
60
+ "E": 4,
61
+ "F": 7,
62
+ "G": 8,
63
+ "N": 0,
64
+ "O": 2,
65
+ "R": 1,
66
+ "S": 6,
67
+ "T": 9})
68
+
69
+
70
+ if __name__ == '__main__':
71
+ unittest.main()
@@ -0,0 +1,29 @@
1
+ from itertools import combinations, permutations
2
+
3
+
4
+ def check_leading_zeros(*numbers):
5
+ return any(n[0] == '0' for n in numbers)
6
+
7
+
8
+ def test_equation(puzzle, substitutions):
9
+ equation = ''.join(substitutions.get(char) or char for char in puzzle)
10
+ left, right = equation.split(' == ')
11
+ left_numbers = left.split(' + ')
12
+
13
+ if check_leading_zeros(right, *left_numbers):
14
+ return False
15
+
16
+ return sum(map(int, left_numbers)) == int(right)
17
+
18
+
19
+ def solve(puzzle):
20
+ letters = set(char for char in puzzle if char.isupper())
21
+ numbers = map(str, range(10))
22
+
23
+ for c in combinations(numbers, len(letters)):
24
+ for p in permutations(c):
25
+ substitutions = dict(zip(letters, p))
26
+ if test_equation(puzzle, substitutions):
27
+ return {k: int(v) for k, v in substitutions.items()}
28
+
29
+ return {} # no solution found
@@ -0,0 +1,2 @@
1
+ def calculate_total():
2
+ pass
@@ -0,0 +1,72 @@
1
+ import unittest
2
+
3
+ from book_store import calculate_total
4
+
5
+
6
+ # test cases adapted from `x-common//canonical-data.json` @ version: 1.0.0
7
+
8
+ class BookStoreTests(unittest.TestCase):
9
+ def test_only_a_single_book(self):
10
+ self.assertAlmostEqual(calculate_total([1]), 8.00,
11
+ places=2)
12
+
13
+ def test_two_of_the_same_book(self):
14
+ self.assertAlmostEqual(calculate_total([2, 2]), 16.00,
15
+ places=2)
16
+
17
+ def test_empty_basket(self):
18
+ self.assertAlmostEqual(calculate_total([]), 0.00,
19
+ places=2)
20
+
21
+ def test_two_different_books(self):
22
+ self.assertAlmostEqual(calculate_total([1, 2]), 15.20,
23
+ places=2)
24
+
25
+ def test_three_different_books(self):
26
+ self.assertAlmostEqual(calculate_total([1, 2, 3]), 21.60,
27
+ places=2)
28
+
29
+ def test_four_different_books(self):
30
+ self.assertAlmostEqual(calculate_total([1, 2, 3, 4]), 25.60,
31
+ places=2)
32
+
33
+ def test_five_different_books(self):
34
+ self.assertAlmostEqual(
35
+ calculate_total([1, 2, 3, 4, 5]), 30.00,
36
+ places=2)
37
+
38
+ def test_two_groups_of_4_is_cheaper_than_group_of_5_plus_group_of_3(self):
39
+ self.assertAlmostEqual(
40
+ calculate_total([1, 1, 2, 2, 3, 3, 4, 5]), 51.20,
41
+ places=2)
42
+
43
+ def test_group_of_4_plus_group_of_2_is_cheaper_than_2_groups_of_3(self):
44
+ self.assertAlmostEqual(
45
+ calculate_total([1, 1, 2, 2, 3, 4]), 40.80,
46
+ places=2)
47
+
48
+ def test_two_each_of_first_4_books_and_1_copy_each_of_rest(self):
49
+ self.assertAlmostEqual(
50
+ calculate_total([1, 1, 2, 2, 3, 3, 4, 4, 5]), 55.60,
51
+ places=2)
52
+
53
+ def test_two_copies_of_each_book(self):
54
+ self.assertAlmostEqual(
55
+ calculate_total([1, 1, 2, 2, 3, 3, 4, 4, 5, 5]), 60.00,
56
+ places=2)
57
+
58
+ def test_three_copies_of_first_book_and_2_each_of_remaining(self):
59
+ self.assertAlmostEqual(
60
+ calculate_total([1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 1]),
61
+ 68.00,
62
+ places=2)
63
+
64
+ def test_three_each_of_first_2_books_and_2_each_of_remaining_books(self):
65
+ self.assertAlmostEqual(
66
+ calculate_total([1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 1, 2]),
67
+ 75.20,
68
+ places=2)
69
+
70
+
71
+ if __name__ == '__main__':
72
+ unittest.main()
@@ -0,0 +1,29 @@
1
+ BOOK_PRICE = 8
2
+
3
+
4
+ def _group_price(size):
5
+ discounts = [0, .05, .1, .2, .25]
6
+ if not (0 < size <= 5):
7
+ raise ValueError('size must be in 1..' + len(discounts))
8
+ return 8 * size * (1 - discounts[size - 1])
9
+
10
+
11
+ def calculate_total(books, price_so_far=0.):
12
+ if not books:
13
+ return price_so_far
14
+
15
+ groups = list(set(books))
16
+ min_price = float('inf')
17
+
18
+ for i in range(len(groups)):
19
+
20
+ remaining_books = books[:]
21
+
22
+ for v in groups[:i + 1]:
23
+ remaining_books.remove(v)
24
+
25
+ price = calculate_total(remaining_books,
26
+ price_so_far + _group_price(i + 1))
27
+ min_price = min(min_price, price)
28
+
29
+ return min_price