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
@@ -0,0 +1,281 @@
1
+ if !System.get_env("EXERCISM_TEST_EXAMPLES") do
2
+ Code.load_file("clock.exs", __DIR__)
3
+ end
4
+
5
+ ExUnit.start
6
+ ExUnit.configure exclude: :pending, trace: true
7
+
8
+ defmodule ClockTest do
9
+ use ExUnit.Case
10
+
11
+ #@tag :pending
12
+ test "to_string" do
13
+ try do
14
+ to_string(%Clock{})
15
+ rescue
16
+ Protocol.UndefinedError ->
17
+ refute(true, """
18
+ Can't convert Clock to string.
19
+ Hint: implement the String.Chars protocol for Clock.
20
+ http://elixir-lang.org/getting-started/protocols.html
21
+ http://elixir-lang.org/docs/stable/elixir/String.Chars.html
22
+ """)
23
+ end
24
+ end
25
+
26
+ describe "create" do
27
+ @tag :pending
28
+ test "on the hour" do
29
+ assert Clock.new(8, 0) |> to_string == "08:00"
30
+ end
31
+
32
+ @tag :pending
33
+ test "past the hour" do
34
+ assert Clock.new(11, 9) |> to_string == "11:09"
35
+ end
36
+
37
+ @tag :pending
38
+ test "midnight is zero hours" do
39
+ assert Clock.new(24, 0) |> to_string == "00:00"
40
+ end
41
+
42
+ @tag :pending
43
+ test "hour rolls over" do
44
+ assert Clock.new(25, 0) |> to_string == "01:00"
45
+ end
46
+
47
+ @tag :pending
48
+ test "hour rolls over continuously" do
49
+ assert Clock.new(100, 0) |> to_string == "04:00"
50
+ end
51
+
52
+ @tag :pending
53
+ test "sixty minutes is next hour" do
54
+ assert Clock.new(1, 60) |> to_string == "02:00"
55
+ end
56
+
57
+ @tag :pending
58
+ test "minutes roll over" do
59
+ assert Clock.new(0, 160) |> to_string == "02:40"
60
+ end
61
+
62
+ @tag :pending
63
+ test "minutes roll over continuously" do
64
+ assert Clock.new(0, 1723) |> to_string == "04:43"
65
+ end
66
+
67
+ @tag :pending
68
+ test "hour and minutes roll over" do
69
+ assert Clock.new(25, 160) |> to_string == "03:40"
70
+ end
71
+
72
+ @tag :pending
73
+ test "hour and minutes roll over continuously" do
74
+ assert Clock.new(201, 3001) |> to_string == "11:01"
75
+ end
76
+
77
+ @tag :pending
78
+ test "hour and minutes roll over to exactly midnight" do
79
+ assert Clock.new(72, 8640) |> to_string == "00:00"
80
+ end
81
+
82
+ @tag :pending
83
+ test "negative hour" do
84
+ assert Clock.new(-1, 15) |> to_string == "23:15"
85
+ end
86
+
87
+ @tag :pending
88
+ test "negative hour rolls over" do
89
+ assert Clock.new(-25, 0) |> to_string == "23:00"
90
+ end
91
+
92
+ @tag :pending
93
+ test "negative hour rolls over continuously" do
94
+ assert Clock.new(-91, 0) |> to_string == "05:00"
95
+ end
96
+
97
+ @tag :pending
98
+ test "negative minutes" do
99
+ assert Clock.new(1, -40) |> to_string == "00:20"
100
+ end
101
+
102
+ @tag :pending
103
+ test "negative minutes roll over" do
104
+ assert Clock.new(1, -160) |> to_string == "22:20"
105
+ end
106
+
107
+ @tag :pending
108
+ test "negative minutes roll over continuously" do
109
+ assert Clock.new(1, -4820) |> to_string == "16:40"
110
+ end
111
+
112
+ @tag :pending
113
+ test "negative hour and minutes roll over" do
114
+ assert Clock.new(-25, -160) |> to_string == "20:20"
115
+ end
116
+
117
+ @tag :pending
118
+ test "negative hour and minutes roll over continuously" do
119
+ assert Clock.new(-121, -5810) |> to_string == "22:10"
120
+ end
121
+ end
122
+
123
+ describe "add" do
124
+ @tag :pending
125
+ test "add minutes" do
126
+ assert Clock.new(10, 0) |> Clock.add(3) |> to_string == "10:03"
127
+ end
128
+
129
+ @tag :pending
130
+ test "add no minutes" do
131
+ assert Clock.new(6, 41) |> Clock.add(0) |> to_string == "06:41"
132
+ end
133
+
134
+ @tag :pending
135
+ test "add to next hour" do
136
+ assert Clock.new(0, 45) |> Clock.add(40) |> to_string == "01:25"
137
+ end
138
+
139
+ @tag :pending
140
+ test "add more than one hour" do
141
+ assert Clock.new(10, 0) |> Clock.add(61) |> to_string == "11:01"
142
+ end
143
+
144
+ @tag :pending
145
+ test "add more than two hours with carry" do
146
+ assert Clock.new(0, 45) |> Clock.add(160) |> to_string == "03:25"
147
+ end
148
+
149
+ @tag :pending
150
+ test "add across midnight" do
151
+ assert Clock.new(23, 59) |> Clock.add(2) |> to_string == "00:01"
152
+ end
153
+
154
+ @tag :pending
155
+ test "add more than one day (1500 min = 25 hrs)" do
156
+ assert Clock.new(5, 32) |> Clock.add(1500) |> to_string == "06:32"
157
+ end
158
+
159
+ @tag :pending
160
+ test "add more than two days" do
161
+ assert Clock.new(1, 1) |> Clock.add(3500) |> to_string == "11:21"
162
+ end
163
+
164
+ @tag :pending
165
+ test "subtract minutes" do
166
+ assert Clock.new(10, 3) |> Clock.add(-3) |> to_string == "10:00"
167
+ end
168
+
169
+ @tag :pending
170
+ test "subtract to previous hour" do
171
+ assert Clock.new(10, 3) |> Clock.add(-30) |> to_string == "09:33"
172
+ end
173
+
174
+ @tag :pending
175
+ test "subtract more than an hour" do
176
+ assert Clock.new(10, 3) |> Clock.add(-70) |> to_string == "08:53"
177
+ end
178
+
179
+ @tag :pending
180
+ test "subtract across midnight" do
181
+ assert Clock.new(0, 3) |> Clock.add(-4) |> to_string == "23:59"
182
+ end
183
+
184
+ @tag :pending
185
+ test "subtract more than two hours" do
186
+ assert Clock.new(0, 0) |> Clock.add(-160) |> to_string == "21:20"
187
+ end
188
+
189
+ @tag :pending
190
+ test "subtract more than two hours with borrow" do
191
+ assert Clock.new(6, 15) |> Clock.add(-160) |> to_string == "03:35"
192
+ end
193
+
194
+ @tag :pending
195
+ test "subtract more than one day (1500 min = 25 hrs)" do
196
+ assert Clock.new(5, 32) |> Clock.add(-1500) |> to_string == "04:32"
197
+ end
198
+
199
+ @tag :pending
200
+ test "subtract more than two days" do
201
+ assert Clock.new(2, 20) |> Clock.add(-3000) |> to_string == "00:20"
202
+ end
203
+ end
204
+
205
+ describe "==" do
206
+ @tag :pending
207
+ test "clocks with same time" do
208
+ assert Clock.new(15, 37) == Clock.new(15, 37)
209
+ end
210
+
211
+ @tag :pending
212
+ test "clocks a minute apart" do
213
+ refute Clock.new(15, 36) == Clock.new(15, 37)
214
+ end
215
+
216
+ @tag :pending
217
+ test "clocks an hour apart" do
218
+ refute Clock.new(14, 37) == Clock.new(15, 37)
219
+ end
220
+
221
+ @tag :pending
222
+ test "clocks with hour overflow" do
223
+ assert Clock.new(10, 37) == Clock.new(34, 37)
224
+ end
225
+
226
+ @tag :pending
227
+ test "clocks with hour overflow by several days" do
228
+ assert Clock.new(3, 11) == Clock.new(99, 11)
229
+ end
230
+
231
+ @tag :pending
232
+ test "clocks with negative hour" do
233
+ assert Clock.new(22, 40) == Clock.new(-2, 40)
234
+ end
235
+
236
+ @tag :pending
237
+ test "clocks with negative hour that wraps" do
238
+ assert Clock.new(17, 3) == Clock.new(-31, 3)
239
+ end
240
+
241
+ @tag :pending
242
+ test "clocks with negative hour that wraps multiple times" do
243
+ assert Clock.new(13, 49) == Clock.new(-83, 49)
244
+ end
245
+
246
+ @tag :pending
247
+ test "clocks with minute overflow" do
248
+ assert Clock.new(0, 1) == Clock.new(0, 1441)
249
+ end
250
+
251
+ @tag :pending
252
+ test "clocks with minute overflow by several days" do
253
+ assert Clock.new(2, 2) == Clock.new(2, 4322)
254
+ end
255
+
256
+ @tag :pending
257
+ test "clocks with negative minute" do
258
+ assert Clock.new(2, 40) == Clock.new(3, -20)
259
+ end
260
+
261
+ @tag :pending
262
+ test "clocks with negative minute that wraps" do
263
+ assert Clock.new(4, 10) == Clock.new(5, -1490)
264
+ end
265
+
266
+ @tag :pending
267
+ test "clocks with negative minute that wraps multiple times" do
268
+ assert Clock.new(6, 15) == Clock.new(6, -4305)
269
+ end
270
+
271
+ @tag :pending
272
+ test "clocks with negative hours and minutes" do
273
+ assert Clock.new(7, 32) == Clock.new(-12, -268)
274
+ end
275
+
276
+ @tag :pending
277
+ test "clocks with negative hours and minutes that wrap" do
278
+ assert Clock.new(18, 7) == Clock.new(-54, -11513)
279
+ end
280
+ end
281
+ end
@@ -0,0 +1,55 @@
1
+ defmodule Clock do
2
+ defstruct hour: 0, minute: 0
3
+ @type t :: %Clock{hour: integer, minute: integer}
4
+ @type t(hour, minute) :: %Clock{hour: hour, minute: minute}
5
+
6
+ @doc """
7
+ Returns a string representation of a clock:
8
+
9
+ iex> Clock.new(8, 9) |> to_string
10
+ "08:09"
11
+ """
12
+ @spec new(integer, integer) :: Clock.t
13
+ def new(hour, minute) do
14
+ rollover(%Clock{hour: hour, minute: minute})
15
+ end
16
+
17
+ @doc """
18
+ Adds two clock times:
19
+
20
+ iex> Clock.new(10, 0) |> Clock.add(3) |> to_string
21
+ "10:03"
22
+ """
23
+ @spec add(Clock.t, integer) :: Clock.t
24
+ def add(%Clock{hour: hour, minute: minute}, add_minute) do
25
+ new(hour, minute + add_minute)
26
+ end
27
+
28
+ defp rollover(%Clock{hour: hour, minute: minute}) do
29
+ {carry_hour, minute} = roll_minute(minute)
30
+ %Clock{hour: roll_hour(hour + carry_hour), minute: minute}
31
+ end
32
+
33
+ defp roll_hour(hour) when hour < 0 and rem(hour, 24) == 0, do: 0
34
+ defp roll_hour(hour) when hour < 0, do: 24 + rem(hour, 24)
35
+ defp roll_hour(hour) when hour >= 24, do: rem(hour, 24)
36
+ defp roll_hour(hour), do: hour
37
+
38
+ defp roll_minute(minute) when minute < 0 do
39
+ {div(minute, 60) - 1, 60 + rem(minute, 60)}
40
+ end
41
+ defp roll_minute(minute) when minute >= 60 do
42
+ {div(minute, 60), rem(minute, 60)}
43
+ end
44
+ defp roll_minute(minute), do: {0, minute}
45
+
46
+ defimpl String.Chars, for: Clock do
47
+ def to_string(%Clock{hour: hour, minute: minute}) do
48
+ "#{format(hour)}:#{format(minute)}"
49
+ end
50
+
51
+ defp format(number) do
52
+ number |> Integer.to_string |> String.pad_leading(2, "0")
53
+ end
54
+ end
55
+ end
@@ -1,10 +1,9 @@
1
1
  defmodule PrimeFactors do
2
2
  @spec factors_for(pos_integer) :: [pos_integer]
3
3
  def factors_for(number) do
4
- do_factors(number)
4
+ do_factors(number, 2, [])
5
5
  end
6
6
 
7
- defp do_factors(_, i \\ 2, acc \\ [])
8
7
  defp do_factors(1, _, acc),
9
8
  do: Enum.reverse(acc)
10
9
  defp do_factors(n, i, acc) when n < i * i,
@@ -27,15 +27,14 @@ defmodule RobotSimulator do
27
27
  def direction(%RobotSimulator{direction: dir}), do: dir
28
28
 
29
29
  defp orient(%RobotSimulator{} = robot, direction) when direction in @valid_directions do
30
- %RobotSimulator{ robot | direction: direction }
30
+ %{ robot | direction: direction }
31
31
  end
32
32
  defp orient({ :error, _ } = error, _), do: error
33
33
  defp orient(_, _), do: { :error, "invalid direction" }
34
34
 
35
35
  defp place(%RobotSimulator{} = robot, { x, y } = position) when is_integer(x) and is_integer(y) do
36
- %RobotSimulator{ robot | position: position }
36
+ %{ robot | position: position }
37
37
  end
38
- defp place({ :error, _ } = error, _), do: error
39
38
  defp place(_, _), do: { :error, "invalid position" }
40
39
 
41
40
  defp move("R", %RobotSimulator{ direction: direction } = robot), do: robot |> orient(direction |> rotate_right)
@@ -6,7 +6,8 @@ defmodule ExercismTestRunner.Mixfile do
6
6
  version: "0.0.1",
7
7
  elixir: "~> 1.3",
8
8
  deps: deps,
9
- test_paths: ["exercises"]]
9
+ test_paths: ["exercises"],
10
+ consolidate_protocols: false]
10
11
  end
11
12
 
12
13
  def application do
@@ -38,7 +38,7 @@ Your first goal it to get something to compile, even though it fails tests. For
38
38
 
39
39
  ### Fixing
40
40
 
41
- Tests will often stop at the first error. Fix that one, repeat until no errors. `go test` has useful options. `go test -v` will give more verbose output. `go test -run <regexp>` will run just tests with names that match <regexp>.
41
+ Tests will often stop at the first error. Fix that one, repeat until no errors. `go test` has useful options. `go test -v` will give more verbose output. `go test -run <regexp>` will run just tests with names that match `<regexp>`.
42
42
 
43
43
  Panics produce lots of output. It might seem scary at first, but be brave. Look at the very top of the panic output for the panic message. That should give a general description of the problem. Then read through the rest of it looking for the first reference to your code. That will often point right to the problem.
44
44
 
@@ -1,8 +1,6 @@
1
1
  package gigasecond
2
2
 
3
3
  // Write a function AddGigasecond that works with time.Time.
4
- // Also define a variable Birthday set to your (or someone else's) birthday.
5
- // Run go test -v to see your gigasecond anniversary.
6
4
 
7
5
  import (
8
6
  "os"
@@ -9,20 +9,15 @@ import (
9
9
 
10
10
  const targetTestVersion = 1
11
11
 
12
- func TestTestVersion(t *testing.T) {
13
- if testVersion != targetTestVersion {
14
- t.Errorf("Found testVersion = %v, want %v.", testVersion, targetTestVersion)
15
- }
16
- }
12
+ /* API to implement:
13
+
14
+ type Product struct {
15
+ Product int // palindromic, of course
16
+ Factorizations [][2]int //list of all possible two-factor factorizations of Product, within given limits, in order
17
+ }
17
18
 
18
- // API to impliment:
19
- // type Product struct {
20
- // Product int // palindromic, of course
21
- // // list of all possible two-factor factorizations of Product, within
22
- // // given limits, in order
23
- // Factorizations [][2]int
24
- // }
25
- // func Products(fmin, fmax int) (pmin, pmax Product, error)
19
+ func Products(fmin, fmax int) (pmin, pmax Product, error)
20
+ */
26
21
 
27
22
  var testData = []struct {
28
23
  // input to Products(): range limits for factors of the palindrome
@@ -45,29 +40,44 @@ var testData = []struct {
45
40
  ""},
46
41
  {4, 10, Product{}, Product{}, "No palindromes"},
47
42
  {10, 4, Product{}, Product{}, "fmin > fmax"},
48
- /* bonus curiosities. (can a negative number be a palindrome?
49
- // most say no
50
- {-99, -10, Product{}, Product{}, "Negative limits"},
51
- // but you can still get non-negative products from negative factors.
43
+ }
44
+
45
+ // Bonus curiosities. Can a negative number be a palindrome? Most say no.
46
+ var bonusData = []struct {
47
+ fmin, fmax int
48
+ pmin, pmax Product
49
+ errPrefix string
50
+ }{
51
+ // The following two test cases have the same input, but different expectations. Uncomment just one or the other.
52
+
53
+ /* Here you can test that you can reach the limit of the largest palindrome made of two 2-digit numbers.
54
+ {-99, -10, Product{}, Product{}, "Negative limits"}, */
55
+
56
+ // You can still get non-negative products from negative factors.
52
57
  {-99, -10,
53
58
  Product{121, [][2]int{{-11, -11}}},
54
59
  Product{9009, [][2]int{{-99, -91}}},
55
60
  ""},
61
+
62
+ // The following two test cases have the same input, but different expectations. Uncomment just one or the other.
63
+
64
+ /*In case you reverse the *digits* you could have the following cases:
65
+ - the zero has to be considered
56
66
  {-2, 2,
57
67
  Product{0, [][2]int{{-2, 0}, {-1, 0}, {0, 0}, {0, 1}, {0, 2}}},
58
68
  Product{4, [][2]int{{-2, -2}, {2, 2}}},
59
- ""},
60
- // or you could reverse the *digits*, keeping the minus sign in place.
69
+ ""}, */
70
+
71
+ // - you can keep the minus sign in place
61
72
  {-2, 2,
62
73
  Product{-4, [][2]int{{-2, 2}}},
63
74
  Product{4, [][2]int{{-2, -2}, {2, 2}}},
64
75
  ""},
65
- {
66
- {0, (^uint(0))>>1, Product{}, Product{}, "This one's gonna overflow"},
67
- */
68
76
  }
69
77
 
70
78
  func TestPalindromeProducts(t *testing.T) {
79
+ // Uncomment the following line to add the bonus test to the default tests
80
+ // testData = append(testData, bonusData...)
71
81
  for _, test := range testData {
72
82
  // common preamble for test failures
73
83
  ret := fmt.Sprintf("Products(%d, %d) returned",
@@ -99,6 +109,12 @@ func TestPalindromeProducts(t *testing.T) {
99
109
  }
100
110
  }
101
111
 
112
+ func TestTestVersion(t *testing.T) {
113
+ if testVersion != targetTestVersion {
114
+ t.Errorf("Found testVersion = %v, want %v.", testVersion, targetTestVersion)
115
+ }
116
+ }
117
+
102
118
  func BenchmarkPalindromeProducts(b *testing.B) {
103
119
  for i := 0; i < b.N; i++ {
104
120
  for _, test := range testData {
@@ -42,6 +42,13 @@ script:
42
42
  SET_RESOLVER="--resolver ${RESOLVER}"
43
43
  fi
44
44
 
45
+ test_exercise () {
46
+ stack test ${SET_RESOLVER} `# Select the correct resolver. `\
47
+ --install-ghc `# Download GHC if not in cache.`\
48
+ --no-terminal `# Terminal detection is broken.`\
49
+ --pedantic `# Enable -Wall and -Werror. `
50
+ }
51
+
45
52
  for exercise in ${TRAVIS_BUILD_DIR}/exercises/* ; do
46
53
  pushd ${exercise}
47
54
 
@@ -50,13 +57,25 @@ script:
50
57
  mkdir -p "${HOME}/.foldercache/${exercise}/.stack-work"
51
58
  ln -f -s "${HOME}/.foldercache/${exercise}/.stack-work"
52
59
 
53
- # Here we prepare the exercise to be tested by Stack.
54
- MODULE=`sed -n 's/ *module \+\([a-zA-Z0-9]\+\).*/\1/p' src/Example.hs`
55
- mv src/Example.hs "src/${MODULE}.hs"
60
+ if [ -f src/Example.hs ]; then
61
+ # Here we prepare the exercise to be tested by Stack.
62
+ MODULE=`sed -n 's/ *module \+\([a-zA-Z0-9]\+\).*/\1/p' src/Example.hs`
63
+ mv src/Example.hs "src/${MODULE}.hs"
64
+
65
+ test_exercise
66
+ elif ! stat -t examples/*/ > /dev/null 2>&1; then
67
+ echo "No examples for ${exercise}!"
68
+ exit 1
69
+ else
70
+ for example in examples/*/ ; do
71
+ echo "testing ${example}"
72
+ rm -f src/*.hs
73
+ mv ${example}/*.hs src
74
+ mv ${example}/package.yaml .
75
+
76
+ test_exercise
77
+ done
78
+ fi
56
79
 
57
- stack test ${SET_RESOLVER} `# Select the correct resolver. `\
58
- --install-ghc `# Download GHC if not in cache.`\
59
- --no-terminal `# Terminal detection is broken.`\
60
- --pedantic `# Enable -Wall and -Werror. `
61
80
  popd
62
81
  done
@@ -3,75 +3,6 @@
3
3
  "language": "Haskell",
4
4
  "repository": "https://github.com/exercism/xhaskell",
5
5
  "active": true,
6
- "problems": [
7
- "leap",
8
- "accumulate",
9
- "sublist",
10
- "grains",
11
- "bob",
12
- "sum-of-multiples",
13
- "strain",
14
- "hamming",
15
- "rna-transcription",
16
- "space-age",
17
- "anagram",
18
- "phone-number",
19
- "nucleotide-count",
20
- "grade-school",
21
- "simple-linked-list",
22
- "list-ops",
23
- "word-count",
24
- "etl",
25
- "robot-name",
26
- "meetup",
27
- "beer-song",
28
- "triangle",
29
- "scrabble-score",
30
- "roman-numerals",
31
- "prime-factors",
32
- "raindrops",
33
- "allergies",
34
- "atbash-cipher",
35
- "all-your-base",
36
- "bank-account",
37
- "crypto-square",
38
- "kindergarten-garden",
39
- "robot-simulator",
40
- "queen-attack",
41
- "binary-search-tree",
42
- "difference-of-squares",
43
- "largest-series-product",
44
- "luhn",
45
- "clock",
46
- "matrix",
47
- "house",
48
- "minesweeper",
49
- "ocr-numbers",
50
- "wordy",
51
- "food-chain",
52
- "linked-list",
53
- "custom-set",
54
- "nth-prime",
55
- "palindrome-products",
56
- "pascals-triangle",
57
- "pig-latin",
58
- "pythagorean-triplet",
59
- "saddle-points",
60
- "say",
61
- "secret-handshake",
62
- "series",
63
- "sieve",
64
- "simple-cipher",
65
- "change",
66
- "connect",
67
- "parallel-letter-frequency",
68
- "sgf-parsing",
69
- "go-counting",
70
- "zipper",
71
- "forth",
72
- "lens-person",
73
- "pov"
74
- ],
75
6
  "exercises": [
76
7
  {
77
8
  "slug": "leap",
@@ -0,0 +1,10 @@
1
+ module Anagram (anagramsFor) where
2
+ import Data.List (sort)
3
+ import Data.Char (toLower)
4
+
5
+ anagramsFor :: String -> [String] -> [String]
6
+ anagramsFor word = filter (isAnagram . normalize)
7
+ where
8
+ normalize xs = let nxs = map toLower xs in (nxs, sort nxs)
9
+ (nw, sw) = normalize word
10
+ isAnagram (w, s) = nw /= w && sw == s
@@ -0,0 +1,17 @@
1
+ name: anagram
2
+
3
+ dependencies:
4
+ - base
5
+
6
+ library:
7
+ exposed-modules: Anagram
8
+ source-dirs: src
9
+ dependencies:
10
+
11
+ tests:
12
+ test:
13
+ main: Tests.hs
14
+ source-dirs: test
15
+ dependencies:
16
+ - anagram
17
+ - hspec
@@ -0,0 +1,20 @@
1
+ name: anagram
2
+
3
+ dependencies:
4
+ - base
5
+
6
+ library:
7
+ exposed-modules: Anagram
8
+ source-dirs: src
9
+ dependencies:
10
+ - containers
11
+ - multiset
12
+ - text
13
+
14
+ tests:
15
+ test:
16
+ main: Tests.hs
17
+ source-dirs: test
18
+ dependencies:
19
+ - anagram
20
+ - hspec
@@ -9,9 +9,6 @@ library:
9
9
  dependencies:
10
10
  # - foo # List here the packages you
11
11
  # - bar # want to use in your solution.
12
- - containers
13
- - multiset
14
- - text
15
12
 
16
13
  tests:
17
14
  test: