trackler 1.0.1.0 → 1.0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1 -0
  3. data/bin/bump-content +33 -0
  4. data/common/exercises/bowling/canonical-data.json +78 -77
  5. data/common/exercises/counter/.deprecated +1 -0
  6. data/common/exercises/point-mutations/.deprecated +1 -0
  7. data/common/exercises/say/canonical-data.json +83 -0
  8. data/common/exercises/word-count/canonical-data.json +25 -5
  9. data/lib/trackler/version.rb +1 -1
  10. data/tracks/c/config.json +9 -0
  11. data/tracks/c/exercises/largest-series-product/makefile +16 -0
  12. data/tracks/c/exercises/largest-series-product/src/example.c +54 -0
  13. data/tracks/c/exercises/largest-series-product/src/example.h +9 -0
  14. data/tracks/c/exercises/largest-series-product/test/test_largest_series_product.c +114 -0
  15. data/tracks/c/exercises/largest-series-product/test/vendor/unity.c +1300 -0
  16. data/tracks/c/exercises/largest-series-product/test/vendor/unity.h +274 -0
  17. data/tracks/c/exercises/largest-series-product/test/vendor/unity_internals.h +701 -0
  18. data/tracks/clojure/_test/check_exercises.clj +7 -6
  19. data/tracks/clojure/config.json +268 -53
  20. data/tracks/clojure/exercises/flatten-array/src/example.clj +16 -0
  21. data/tracks/clojure/exercises/flatten-array/test/flatten_array_test.clj +28 -0
  22. data/tracks/clojure/exercises/perfect-numbers/project.clj +4 -0
  23. data/tracks/clojure/exercises/perfect-numbers/src/example.clj +17 -0
  24. data/tracks/clojure/exercises/perfect-numbers/test/perfect_numbers_test.clj +20 -0
  25. data/tracks/ecmascript/exercises/grade-school/grade-school.spec.js +7 -0
  26. data/tracks/elixir/.travis.yml +3 -0
  27. data/tracks/elixir/bin/dialyzer_check.sh +28 -0
  28. data/tracks/elixir/config.json +13 -1
  29. data/tracks/elixir/docs/TESTS.md +81 -0
  30. data/tracks/elixir/exercises/bank-account/example.exs +1 -1
  31. data/tracks/elixir/exercises/binary-search/binary_search_test.exs +5 -0
  32. data/tracks/elixir/exercises/clock/clock.exs +23 -0
  33. data/tracks/elixir/exercises/clock/clock_test.exs +281 -0
  34. data/tracks/elixir/exercises/clock/example.exs +55 -0
  35. data/tracks/elixir/exercises/prime-factors/example.exs +1 -2
  36. data/tracks/elixir/exercises/robot-simulator/example.exs +2 -3
  37. data/tracks/elixir/mix.exs +2 -1
  38. data/tracks/go/docs/TESTS.md +1 -1
  39. data/tracks/go/exercises/gigasecond/gigasecond_test.go +0 -2
  40. data/tracks/go/exercises/palindrome-products/palindrome_products_test.go +38 -22
  41. data/tracks/haskell/.travis.yml +26 -7
  42. data/tracks/haskell/config.json +0 -69
  43. data/tracks/haskell/exercises/anagram/examples/list-string/Anagram.hs +10 -0
  44. data/tracks/haskell/exercises/anagram/examples/list-string/package.yaml +17 -0
  45. data/tracks/haskell/exercises/anagram/{src/Example.hs → examples/set-text/Anagram.hs} +0 -0
  46. data/tracks/haskell/exercises/anagram/examples/set-text/package.yaml +20 -0
  47. data/tracks/haskell/exercises/anagram/package.yaml +0 -3
  48. data/tracks/idris/config.json +3 -3
  49. data/tracks/kotlin/config.json +207 -43
  50. data/tracks/lfe/config.json +152 -32
  51. data/tracks/lfe/docs/TESTS.md +18 -56
  52. data/tracks/lua/docs/ABOUT.md +9 -0
  53. data/tracks/mips/config.json +72 -16
  54. data/tracks/ocaml/config.json +6 -0
  55. data/tracks/ocaml/exercises/etl/.merlin +5 -0
  56. data/tracks/ocaml/exercises/etl/Makefile +11 -0
  57. data/tracks/ocaml/exercises/etl/etl.mli +2 -0
  58. data/tracks/ocaml/exercises/etl/example.ml +7 -0
  59. data/tracks/ocaml/exercises/etl/test.ml +35 -0
  60. data/tracks/ocaml/exercises/raindrops/test.ml +1 -1
  61. data/tracks/php/config.json +7 -1
  62. data/tracks/php/exercises/acronym/acronym_test.php +56 -0
  63. data/tracks/php/exercises/acronym/example.php +20 -0
  64. data/tracks/racket/config.json +109 -22
  65. data/tracks/ruby/README.md +3 -3
  66. data/tracks/ruby/bin/generate +16 -0
  67. data/tracks/ruby/exercises/alphametics/.version +1 -1
  68. data/tracks/ruby/exercises/alphametics/alphametics_test.rb +24 -22
  69. data/tracks/ruby/exercises/alphametics/example.rb +1 -1
  70. data/tracks/ruby/lib/bracket_push_cases.rb +3 -3
  71. data/tracks/ruby/lib/{raindrop_cases.rb → raindrops_cases.rb} +1 -1
  72. data/tracks/rust/config.json +1 -0
  73. data/tracks/rust/exercises/atbash-cipher/Cargo.lock +4 -0
  74. data/tracks/rust/exercises/atbash-cipher/Cargo.toml +3 -0
  75. data/tracks/rust/exercises/atbash-cipher/example.rs +36 -0
  76. data/tracks/rust/exercises/atbash-cipher/tests/atbash-cipher.rs +82 -0
  77. data/tracks/rust/problems.md +1 -0
  78. data/tracks/scala/config.json +8 -0
  79. data/tracks/scala/exercises/sum-of-multiples/build.sbt +3 -0
  80. data/tracks/scala/exercises/sum-of-multiples/example.scala +10 -0
  81. data/tracks/scala/exercises/sum-of-multiples/src/main/scala/.keep +0 -0
  82. data/tracks/scala/exercises/sum-of-multiples/src/test/scala/SumOfMultiplesTest.scala +62 -0
  83. metadata +43 -23
  84. data/tracks/ruby/bin/generate-acronym +0 -7
  85. data/tracks/ruby/bin/generate-alphametics +0 -8
  86. data/tracks/ruby/bin/generate-binary +0 -7
  87. data/tracks/ruby/bin/generate-bracket-push +0 -7
  88. data/tracks/ruby/bin/generate-clock +0 -7
  89. data/tracks/ruby/bin/generate-connect +0 -7
  90. data/tracks/ruby/bin/generate-custom-set +0 -7
  91. data/tracks/ruby/bin/generate-difference-of-squares +0 -7
  92. data/tracks/ruby/bin/generate-gigasecond +0 -7
  93. data/tracks/ruby/bin/generate-hamming +0 -7
  94. data/tracks/ruby/bin/generate-hello-world +0 -7
  95. data/tracks/ruby/bin/generate-largest-series-product +0 -7
  96. data/tracks/ruby/bin/generate-leap +0 -7
  97. data/tracks/ruby/bin/generate-nth-prime +0 -7
  98. data/tracks/ruby/bin/generate-pangram +0 -7
  99. data/tracks/ruby/bin/generate-raindrops +0 -7
  100. data/tracks/ruby/bin/generate-rna-transcription +0 -7
  101. data/tracks/ruby/bin/generate-roman-numerals +0 -7
  102. data/tracks/ruby/bin/generate-run-length-encoding +0 -7
  103. data/tracks/ruby/bin/generate-two-bucket +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5df79b2829329101c3131df1e1e3c55750ec5d44
4
- data.tar.gz: 3312337a6c8201dab2e6e9fb2f49251ed335bce3
3
+ metadata.gz: 9afe3a2389f45df29805ba631f6e4c4afc5c66ef
4
+ data.tar.gz: bebab04f762c5ee338b0e5a4d645985db6b5034b
5
5
  SHA512:
6
- metadata.gz: 6bad132c234e35b53d232967dfb4f89bdadf921006cc552b9a2065d56065f5aef9e3da3617fc1a2a52b5800a1deb5326d86a6df6e2a5ce296673f8facda6b9ea
7
- data.tar.gz: 1c3046428aaa9d6cf4e1b969701b226ff42a255b621549dc7991213e2e36554ae7f4293e0204b801c1bcd11a364eec7be4bd1528d7f1b8ad27bee15fd549bc95
6
+ metadata.gz: 744116cb977fbed40d585e95a734cedf12e60c2277a703826e39e74e4525881333fed0ca7e4cc3d3add5432df76b6a681bf2c12c3ae7f2223c0bb83313cfd6fd
7
+ data.tar.gz: 3932ddf8a13ac14ab7e0c0c4baaccb9cf15f7e0b4278d3411c34c07523dae0d07ff397d474a2c0e2904c71b6add9887d8c4f30d6882b6839dd1824f007c91688
data/CHANGELOG.md CHANGED
@@ -13,6 +13,7 @@ The changelog will not be updated for content updates.
13
13
  ----------------
14
14
 
15
15
  ## Next Release
16
+ * Add script to update submodules and bump version
16
17
  * **Your contribution here**
17
18
 
18
19
  ## v1.0.1.0 (2016-10-16)
data/bin/bump-content ADDED
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ system("bin/update")
4
+
5
+ file = File.absolute_path("../../lib/trackler/version.rb", __FILE__)
6
+
7
+ contents = File.read(file)
8
+ major, minor, patch, data = contents[/\ \ VERSION\ =\ "(.*)"/, 1].split(".")
9
+
10
+ version = [major, minor, patch, data.to_i + 1].join(".")
11
+
12
+ template = <<-TEMPLATE % version
13
+ module Trackler
14
+ VERSION = "%s"
15
+ end
16
+ TEMPLATE
17
+
18
+ File.open(file, "w") do |f|
19
+ f.puts template
20
+ end
21
+
22
+ cmds = [
23
+ "git add lib/trackler/version.rb",
24
+ "git commit -m 'Bump to v%s'" % version,
25
+ "git tag v%s" % version,
26
+ "git push origin master",
27
+ "git push --tags",
28
+ "gem build trackler.gemspec",
29
+ "gem install --local trackler-%s.gem" % version,
30
+ "gem push trackler-%s.gem" % version,
31
+ ].each do |cmd|
32
+ system cmd
33
+ end
@@ -1,117 +1,118 @@
1
1
  {
2
2
  "#": [
3
- "Bowling is game where players roll a heavy ball to knock down pins",
4
- "arranged in a triangle. Write code to keep track of the score of a",
5
- "game of bowling."
3
+ "Students should implement roll and score methods.",
4
+ "Roll should accept a single integer.",
5
+ "Score should return the game's final score, when possible",
6
+ "For brevity the tests display all the rolls in an array;",
7
+ "each element of the rolls array should be passed to the roll method",
8
+ "The final tests define situations where the score can not be returned",
9
+ "The expection for these tests is -1, indicating an error",
10
+ "In these cases you should expect an error as is idiomatic for your language",
11
+ "When to error is also left up to your implementation. There are two options",
12
+ " - Error as soon as an invalid roll is made",
13
+ " - Error when scoring a game with an invalid roll",
14
+ "You can also error in both cases."
6
15
  ],
7
- "methods": {
8
- "description": [
9
- "Check the public API is correct."
10
- ],
11
- "cases": [{
12
- "description": "must be able to roll with a number of pins",
13
- "method": "roll",
14
- "arity": 1
15
- }, {
16
- "description": "must have a score",
17
- "method": "score",
18
- "arity": 0
19
- }]
20
- },
21
16
  "score": {
22
17
  "description": [
23
- "Check game can be scored correctly."
18
+ "Returns the final score of a bowling game"
24
19
  ],
25
20
  "cases": [{
26
- "description": "should be able to score open frame",
27
- "rolls": [3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
28
- "expected": 7
29
- }, {
30
- "description": "should be able to score multiple frames",
31
- "rolls": [3, 4, 2, 3, 5, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
32
- "expected": 19
33
- }, {
34
- "description": "should be able to score a game with all gutterballs",
21
+ "description": "should be able to score a game with all zeros",
35
22
  "rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
36
23
  "expected": 0
37
24
  }, {
38
- "description": "should be able to score a game with all single pin rolls",
39
- "rolls": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
40
- "expected": 20
41
- }, {
42
- "description": "should be able to score a game with all open frames",
25
+ "description": "should be able to score a game with no strikes or spares",
43
26
  "rolls": [3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6],
44
27
  "expected": 90
45
28
  }, {
46
- "description": "should be able to score a strike not in the last frame",
29
+ "description": "a spare followed by zeros is worth ten points",
30
+ "rolls": [6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
31
+ "expected": 10
32
+ }, {
33
+ "description": "points scored in the roll after a spare are counted twice",
34
+ "rolls": [6, 4, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
35
+ "expected": 16
36
+ }, {
37
+ "description": "consecutive spares each get a one roll bonus",
38
+ "rolls": [5, 5, 3, 7, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
39
+ "expected": 31
40
+ }, {
41
+ "description": "a spare in the last frame gets a one roll bonus that is counted once",
42
+ "rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3, 7],
43
+ "expected": 17
44
+ }, {
45
+ "description": "a strike earns ten points in frame with a single roll",
46
+ "rolls": [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
47
+ "expected": 10
48
+ }, {
49
+ "description": "points scored in the two rolls after a strike are counted twice as a bonus",
47
50
  "rolls": [10, 5, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
48
51
  "expected": 26
49
52
  }, {
50
- "description": "should be able to score a spare not in the last frame",
51
- "rolls": [5, 5, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
52
- "expected": 20
53
- }, {
54
- "description": "should be able to score multiple strikes in a row",
53
+ "description": "consecutive strikes each get the two roll bonus",
55
54
  "rolls": [10, 10, 10, 5, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
56
55
  "expected": 81
57
56
  }, {
58
- "description": "should be able to score multiple spares in a row",
59
- "rolls": [5, 5, 3, 7, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
60
- "expected": 32
61
- }, {
62
- "description": "should allow fill balls when the last frame is a strike",
57
+ "description": "a strike in the last frame gets a two roll bonus that is counted once",
63
58
  "rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 7, 1],
64
59
  "expected": 18
65
60
  }, {
66
- "description": "should allow fill ball when the last frame is a spare",
67
- "rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 1, 7],
68
- "expected": 17
61
+ "description": "rolling a spare with the two roll bonus does not get a bonus roll",
62
+ "rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 7, 3],
63
+ "expected": 20
69
64
  }, {
70
- "description": "should allow fill balls to be a strike",
65
+ "description": "strikes with the two roll bonus do not get bonus rolls",
71
66
  "rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10],
72
67
  "expected": 30
73
68
  }, {
74
- "description": "should be able to score a perfect game",
69
+ "description": "a strike with the one roll bonus after a spare in the last frame does not get a bonus",
70
+ "rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3, 10],
71
+ "expected": 20
72
+ }, {
73
+ "description": "all strikes is a perfect game",
75
74
  "rolls": [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10],
76
75
  "expected": 300
77
- }]
78
- },
79
- "validations": {
80
- "description": [
81
- "Check game rules."
82
- ],
83
- "cases": [{
84
- "description": "should not allow rolls with negative pins",
85
- "rolls": [-1],
86
- "expected": "Pins must have a value from 0 to 10"
87
76
  }, {
88
- "description": "should not allow rolls better than strike",
89
- "rolls": [11],
90
- "expected": "Pins must have a value from 0 to 10"
77
+ "description": "Rolls can not score negative points",
78
+ "rolls": [-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
79
+ "expected": -1
91
80
  }, {
92
- "description": "should not allow two normal rolls better than strike",
93
- "rolls": [5, 6],
94
- "expected": "Pin count exceeds pins on the lane"
81
+ "description": "A roll can not score more than 10 points",
82
+ "rolls": [11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
83
+ "expected": -1
95
84
  }, {
96
- "description": "should not allow two normal rolls better than strike in last frame",
97
- "rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6],
98
- "expected": "Pin count exceeds pins on the lane"
85
+ "description": "Two rolls in a frame can not score more than 10 points",
86
+ "rolls": [5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
87
+ "expected": -1
99
88
  }, {
100
- "description": "should not allow to take score at the beginning of the game",
89
+ "description": "Two bonus rolls after a strike in the last frame can not score more than 10 points",
90
+ "rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 5, 6],
91
+ "expected": -1
92
+ }, {
93
+ "description": "An unstarted game can not be scored",
101
94
  "rolls": [],
102
- "expected": "Score cannot be taken until the end of the game"
95
+ "expected": -1
103
96
  }, {
104
- "description": "should not allow to take score before the game has ended",
105
- "rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
106
- "expected": "Score cannot be taken until the end of the game"
97
+ "description": "An incomplete game can not be scored",
98
+ "rolls": [0, 0],
99
+ "expected": -1
107
100
  }, {
108
- "description": "should not allow rolls after the tenth frame",
101
+ "description": "A game with more than ten frames can not be scored",
109
102
  "rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
110
- "expected": "Should not be able to roll after game is over"
103
+ "expected": -1
104
+ }, {
105
+ "description": "bonus rolls for a strike in the last frame must be rolled before score can be calculated",
106
+ "rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10],
107
+ "expected": -1
108
+ }, {
109
+ "description": "both bonus rolls for a strike in the last frame must be rolled before score can be calculated",
110
+ "rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10],
111
+ "expected": -1
111
112
  }, {
112
- "description": "should not calculate score before fill balls have been played",
113
- "rolls": [10, 10, 10, 10, 10, 10, 10, 10, 10, 10],
114
- "expected": "Score cannot be taken until the end of the game"
113
+ "description": "bonus roll for a spare in the last frame must be rolled before score can be calculated",
114
+ "rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3],
115
+ "expected": -1
115
116
  }]
116
117
  }
117
118
  }
@@ -0,0 +1 @@
1
+ **NOTE: This exercise has been deprecated.**
@@ -0,0 +1 @@
1
+ **NOTE: This exercise has been deprecated.**
@@ -0,0 +1,83 @@
1
+ {
2
+ "#": [
3
+ "Here -1 is used as expected value to indicate that the",
4
+ "input value is out of the range described in the exercise."
5
+ ],
6
+ "cases": [
7
+ {
8
+ "description": "zero",
9
+ "input": 0,
10
+ "expected": "zero"
11
+ },
12
+ {
13
+ "description": "one",
14
+ "input": 1,
15
+ "expected": "one"
16
+ },
17
+ {
18
+ "description": "fourteen",
19
+ "input": 14,
20
+ "expected": "fourteen"
21
+ },
22
+ {
23
+ "description": "twenty",
24
+ "input": 20,
25
+ "expected": "twenty"
26
+ },
27
+ {
28
+ "description": "twenty-two",
29
+ "input": 22,
30
+ "expected": "twenty-two"
31
+ },
32
+ {
33
+ "description": "one hundred",
34
+ "input": 100,
35
+ "expected": "one hundred"
36
+ },
37
+ {
38
+ "description": "one hundred twenty-three",
39
+ "input": 123,
40
+ "expected": "one hundred twenty-three"
41
+ },
42
+ {
43
+ "description": "one thousand",
44
+ "input": 1000,
45
+ "expected": "one thousand"
46
+ },
47
+ {
48
+ "description": "one thousand two hundred thirty-four",
49
+ "input": 1234,
50
+ "expected": "one thousand two hundred thirty-four"
51
+ },
52
+ {
53
+ "description": "one million",
54
+ "input": 1000000,
55
+ "expected": "one million"
56
+ },
57
+ {
58
+ "description": "one million two thousand three hundred forty-five",
59
+ "input": 1002345,
60
+ "expected": "one million two thousand three hundred forty-five"
61
+ },
62
+ {
63
+ "description": "one billion",
64
+ "input": 1000000000,
65
+ "expected": "one billion"
66
+ },
67
+ {
68
+ "description": "a big number",
69
+ "input": 987654321123,
70
+ "expected": "nine hundred eighty-seven billion six hundred fifty-four million three hundred twenty-one thousand one hundred twenty-three"
71
+ },
72
+ {
73
+ "description": "numbers below zero are out of range",
74
+ "input": -1,
75
+ "expected": -1
76
+ },
77
+ {
78
+ "description": "numbers above 999,999,999,999 are out of range",
79
+ "input": 1000000000000,
80
+ "expected": -1
81
+ }
82
+ ]
83
+ }
@@ -13,22 +13,42 @@
13
13
  {
14
14
  "description": "multiple occurrences of a word",
15
15
  "input": "one fish two fish red fish blue fish",
16
- "expected": { "one" : 1, "fish" : 4, "two" : 1, "red" : 1, "blue" : 1 }
16
+ "expected": { "one": 1, "fish": 4, "two": 1, "red": 1, "blue": 1 }
17
+ },
18
+ {
19
+ "description": "handles cramped lists",
20
+ "input": "one,two,three",
21
+ "expected": { "one": 1, "two": 1, "three": 1 }
22
+ },
23
+ {
24
+ "description": "handles expanded lists",
25
+ "input": "one,\ntwo,\nthree",
26
+ "expected": { "one": 1, "two": 1, "three": 1 }
17
27
  },
18
28
  {
19
29
  "description": "ignore punctuation",
20
- "input": "car : carpet as java : javascript!!&@$%^&",
21
- "expected": { "car" : 1, "carpet" : 1, "as" : 1, "java" : 1, "javascript" : 1 }
30
+ "input": "car: carpet as java: javascript!!&@$%^&",
31
+ "expected": { "car": 1, "carpet": 1, "as": 1, "java": 1, "javascript": 1 }
22
32
  },
23
33
  {
24
34
  "description": "include numbers",
25
35
  "input": "testing, 1, 2 testing",
26
- "expected": { "testing" : 2, "1" : 1, "2" : 1 }
36
+ "expected": { "testing": 2, "1": 1, "2": 1 }
27
37
  },
28
38
  {
29
39
  "description": "normalize case",
30
40
  "input": "go Go GO Stop stop",
31
- "expected": { "go" : 3, "stop" : 2 }
41
+ "expected": { "go": 3, "stop": 2 }
42
+ },
43
+ {
44
+ "description": "with apostrophes",
45
+ "input": "First: don't laugh. Then: don't cry.",
46
+ "expected": { "first": 1, "don't": 2, "laugh": 1, "then": 1, "cry": 1 }
47
+ },
48
+ {
49
+ "description": "with_quotations",
50
+ "input": "Joe can't tell between 'large' and large.",
51
+ "expected": { "joe": 1, "can't": 1, "tell": 1, "between": 1, "large": 2, "and": 1 }
32
52
  }
33
53
  ]
34
54
  }
@@ -1,3 +1,3 @@
1
1
  module Trackler
2
- VERSION = "1.0.1.0"
2
+ VERSION = "1.0.1.1"
3
3
  end
data/tracks/c/config.json CHANGED
@@ -13,6 +13,7 @@
13
13
  "raindrops",
14
14
  "bob",
15
15
  "grains",
16
+ "largest-series-product",
16
17
  "pangram",
17
18
  "nth-prime",
18
19
  "beer-song",
@@ -81,6 +82,14 @@
81
82
  "bitwise operations",
82
83
  "performance optimizations"
83
84
  ]
85
+ }, {
86
+ "difficulty": 5,
87
+ "slug": "largest-series-product",
88
+ "topics": [
89
+ "control-flow (loops)",
90
+ "strings",
91
+ "performance optimizations"
92
+ ]
84
93
  }, {
85
94
  "difficulty": 3,
86
95
  "slug": "pangram",
@@ -0,0 +1,16 @@
1
+ CFLAGS = -std=c99
2
+ CFLAGS += -Wall
3
+ CFLAGS += -Wextra
4
+ CFLAGS += -pedantic
5
+ CFLAGS += -Werror
6
+
7
+
8
+ test: tests.out
9
+ @./tests.out
10
+
11
+ clean:
12
+ rm -f *.o *.out
13
+
14
+ tests.out: test/test_largest_series_product.c src/largest_series_product.c src/largest_series_product.h
15
+ @echo Compiling $@
16
+ @cc $(CFLAGS) src/largest_series_product.c test/vendor/unity.c test/test_largest_series_product.c -o tests.out
@@ -0,0 +1,54 @@
1
+ #include <string.h>
2
+ #include <stdbool.h>
3
+ #include "largest_series_product.h"
4
+
5
+ #define MAX(x, y) (x) > (y) ? (x) : (y)
6
+
7
+ static int to_int(char c)
8
+ {
9
+ return c - '0';
10
+ }
11
+
12
+ static bool is_digit(char c)
13
+ {
14
+ return (c >= '0') && (c <= '9');
15
+ }
16
+
17
+ int64_t largest_series_product(char *digits, size_t span)
18
+ {
19
+ size_t digit_count = strlen(digits);
20
+ size_t zeros = 0;
21
+ long product = 1;
22
+ long largest_product = 0;
23
+
24
+ if (span > digit_count)
25
+ return -1;
26
+
27
+ if (!span && !digit_count)
28
+ return 1;
29
+
30
+ for (size_t i = 0; i < digit_count; i++) {
31
+ if (!is_digit(digits[i]))
32
+ return -1;
33
+
34
+ int to_add = to_int(digits[i]);
35
+
36
+ if (i >= span) {
37
+ int to_remove = to_int(digits[i - span]);
38
+ if (to_remove == 0)
39
+ zeros--;
40
+ else
41
+ product /= to_remove;
42
+ }
43
+
44
+ if (to_add > 0)
45
+ product *= to_add;
46
+ else
47
+ zeros++;
48
+
49
+ if ((i + 1 >= span) && (zeros == 0))
50
+ largest_product = MAX(largest_product, product);
51
+ }
52
+
53
+ return largest_product;
54
+ }
@@ -0,0 +1,9 @@
1
+ #ifndef _LARGEST_SERIES_PRODUCT_H
2
+ #define _LARGEST_SERIES_PRODUCT_H
3
+
4
+ #include <stddef.h>
5
+ #include <stdint.h>
6
+
7
+ int64_t largest_series_product(char *digits, size_t span);
8
+
9
+ #endif
@@ -0,0 +1,114 @@
1
+ #include "vendor/unity.h"
2
+ #include "../src/largest_series_product.h"
3
+
4
+ void test_can_find_the_largest_product_of_2_with_numbers_in_order(void)
5
+ {
6
+ TEST_ASSERT_EQUAL(72, largest_series_product("0123456789", 2));
7
+ }
8
+
9
+ void test_can_find_the_largest_product_of_2(void)
10
+ {
11
+ TEST_ASSERT_EQUAL(48, largest_series_product("576802143", 2));
12
+ }
13
+
14
+ void test_finds_the_largest_product_if_span_equals_length(void)
15
+ {
16
+ TEST_ASSERT_EQUAL(18, largest_series_product("29", 2));
17
+ }
18
+
19
+ void test_can_find_the_largest_product_of_3_with_numbers_in_order(void)
20
+ {
21
+ TEST_ASSERT_EQUAL(504, largest_series_product("0123456789", 3));
22
+ }
23
+
24
+ void test_can_find_the_largest_product_of_3(void)
25
+ {
26
+ TEST_ASSERT_EQUAL(270, largest_series_product("1027839564", 3));
27
+ }
28
+
29
+ void test_can_find_the_largest_product_of_5_with_numbers_in_order(void)
30
+ {
31
+ TEST_ASSERT_EQUAL(15120, largest_series_product("0123456789", 5));
32
+ }
33
+
34
+ void test_can_get_the_largest_product_of_a_big_number(void)
35
+ {
36
+ TEST_ASSERT_EQUAL(23520,
37
+ largest_series_product
38
+ ("73167176531330624919225119674426574742355349194934", 6));
39
+ }
40
+
41
+ void test_can_get_the_largest_product_of_a_big_number_ii(void)
42
+ {
43
+ TEST_ASSERT_EQUAL(28350,
44
+ largest_series_product
45
+ ("52677741234314237566414902593461595376319419139427", 6));
46
+ }
47
+
48
+ void test_can_get_the_largest_product_of_a_big_number_project_euler(void)
49
+ {
50
+ TEST_ASSERT_EQUAL_INT64(23514624000,
51
+ largest_series_product
52
+ ("7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450",
53
+ 13));
54
+ }
55
+
56
+ void test_reports_zero_if_the_only_digits_are_zero(void)
57
+ {
58
+ TEST_ASSERT_EQUAL(0, largest_series_product("0000", 2));
59
+ }
60
+
61
+ void test_reports_zero_if_all_spans_include_zero(void)
62
+ {
63
+ TEST_ASSERT_EQUAL(0, largest_series_product("99099", 3));
64
+ }
65
+
66
+ void test_rejects_span_longer_than_string_length(void)
67
+ {
68
+ TEST_ASSERT_EQUAL(-1, largest_series_product("123", 4));
69
+ }
70
+
71
+ void test_reports_1_for_empty_string_and_empty_product_(void)
72
+ {
73
+ TEST_ASSERT_EQUAL(1, largest_series_product("", 0));
74
+ }
75
+
76
+ void test_reports_1_for_nonempty_string_and_empty_product_(void)
77
+ {
78
+ TEST_ASSERT_EQUAL(1, largest_series_product("123", 0));
79
+ }
80
+
81
+ void test_rejects_empty_string_and_nonzero_span(void)
82
+ {
83
+ TEST_ASSERT_EQUAL(-1, largest_series_product("", 1));
84
+ }
85
+
86
+ void test_rejects_invalid_character_in_digits(void)
87
+ {
88
+ TEST_ASSERT_EQUAL(-1, largest_series_product("123a5", 2));
89
+ }
90
+
91
+ int main(void)
92
+ {
93
+ UnityBegin("largest_series_product.c");
94
+
95
+ RUN_TEST(test_can_find_the_largest_product_of_2_with_numbers_in_order);
96
+ RUN_TEST(test_can_find_the_largest_product_of_2);
97
+ RUN_TEST(test_finds_the_largest_product_if_span_equals_length);
98
+ RUN_TEST(test_can_find_the_largest_product_of_3_with_numbers_in_order);
99
+ RUN_TEST(test_can_find_the_largest_product_of_3);
100
+ RUN_TEST(test_can_find_the_largest_product_of_5_with_numbers_in_order);
101
+ RUN_TEST(test_can_get_the_largest_product_of_a_big_number);
102
+ RUN_TEST(test_can_get_the_largest_product_of_a_big_number_ii);
103
+ RUN_TEST(test_can_get_the_largest_product_of_a_big_number_project_euler);
104
+ RUN_TEST(test_reports_zero_if_the_only_digits_are_zero);
105
+ RUN_TEST(test_reports_zero_if_all_spans_include_zero);
106
+ RUN_TEST(test_rejects_span_longer_than_string_length);
107
+ RUN_TEST(test_reports_1_for_empty_string_and_empty_product_);
108
+ RUN_TEST(test_reports_1_for_nonempty_string_and_empty_product_);
109
+ RUN_TEST(test_rejects_empty_string_and_nonzero_span);
110
+ RUN_TEST(test_rejects_invalid_character_in_digits);
111
+
112
+ UnityEnd();
113
+ return 0;
114
+ }