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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1 -0
- data/bin/bump-content +33 -0
- data/common/exercises/bowling/canonical-data.json +78 -77
- data/common/exercises/counter/.deprecated +1 -0
- data/common/exercises/point-mutations/.deprecated +1 -0
- data/common/exercises/say/canonical-data.json +83 -0
- data/common/exercises/word-count/canonical-data.json +25 -5
- data/lib/trackler/version.rb +1 -1
- data/tracks/c/config.json +9 -0
- data/tracks/c/exercises/largest-series-product/makefile +16 -0
- data/tracks/c/exercises/largest-series-product/src/example.c +54 -0
- data/tracks/c/exercises/largest-series-product/src/example.h +9 -0
- data/tracks/c/exercises/largest-series-product/test/test_largest_series_product.c +114 -0
- data/tracks/c/exercises/largest-series-product/test/vendor/unity.c +1300 -0
- data/tracks/c/exercises/largest-series-product/test/vendor/unity.h +274 -0
- data/tracks/c/exercises/largest-series-product/test/vendor/unity_internals.h +701 -0
- data/tracks/clojure/_test/check_exercises.clj +7 -6
- data/tracks/clojure/config.json +268 -53
- data/tracks/clojure/exercises/flatten-array/src/example.clj +16 -0
- data/tracks/clojure/exercises/flatten-array/test/flatten_array_test.clj +28 -0
- data/tracks/clojure/exercises/perfect-numbers/project.clj +4 -0
- data/tracks/clojure/exercises/perfect-numbers/src/example.clj +17 -0
- data/tracks/clojure/exercises/perfect-numbers/test/perfect_numbers_test.clj +20 -0
- data/tracks/ecmascript/exercises/grade-school/grade-school.spec.js +7 -0
- data/tracks/elixir/.travis.yml +3 -0
- data/tracks/elixir/bin/dialyzer_check.sh +28 -0
- data/tracks/elixir/config.json +13 -1
- data/tracks/elixir/docs/TESTS.md +81 -0
- data/tracks/elixir/exercises/bank-account/example.exs +1 -1
- data/tracks/elixir/exercises/binary-search/binary_search_test.exs +5 -0
- data/tracks/elixir/exercises/clock/clock.exs +23 -0
- data/tracks/elixir/exercises/clock/clock_test.exs +281 -0
- data/tracks/elixir/exercises/clock/example.exs +55 -0
- data/tracks/elixir/exercises/prime-factors/example.exs +1 -2
- data/tracks/elixir/exercises/robot-simulator/example.exs +2 -3
- data/tracks/elixir/mix.exs +2 -1
- data/tracks/go/docs/TESTS.md +1 -1
- data/tracks/go/exercises/gigasecond/gigasecond_test.go +0 -2
- data/tracks/go/exercises/palindrome-products/palindrome_products_test.go +38 -22
- data/tracks/haskell/.travis.yml +26 -7
- data/tracks/haskell/config.json +0 -69
- data/tracks/haskell/exercises/anagram/examples/list-string/Anagram.hs +10 -0
- data/tracks/haskell/exercises/anagram/examples/list-string/package.yaml +17 -0
- data/tracks/haskell/exercises/anagram/{src/Example.hs → examples/set-text/Anagram.hs} +0 -0
- data/tracks/haskell/exercises/anagram/examples/set-text/package.yaml +20 -0
- data/tracks/haskell/exercises/anagram/package.yaml +0 -3
- data/tracks/idris/config.json +3 -3
- data/tracks/kotlin/config.json +207 -43
- data/tracks/lfe/config.json +152 -32
- data/tracks/lfe/docs/TESTS.md +18 -56
- data/tracks/lua/docs/ABOUT.md +9 -0
- data/tracks/mips/config.json +72 -16
- data/tracks/ocaml/config.json +6 -0
- data/tracks/ocaml/exercises/etl/.merlin +5 -0
- data/tracks/ocaml/exercises/etl/Makefile +11 -0
- data/tracks/ocaml/exercises/etl/etl.mli +2 -0
- data/tracks/ocaml/exercises/etl/example.ml +7 -0
- data/tracks/ocaml/exercises/etl/test.ml +35 -0
- data/tracks/ocaml/exercises/raindrops/test.ml +1 -1
- data/tracks/php/config.json +7 -1
- data/tracks/php/exercises/acronym/acronym_test.php +56 -0
- data/tracks/php/exercises/acronym/example.php +20 -0
- data/tracks/racket/config.json +109 -22
- data/tracks/ruby/README.md +3 -3
- data/tracks/ruby/bin/generate +16 -0
- data/tracks/ruby/exercises/alphametics/.version +1 -1
- data/tracks/ruby/exercises/alphametics/alphametics_test.rb +24 -22
- data/tracks/ruby/exercises/alphametics/example.rb +1 -1
- data/tracks/ruby/lib/bracket_push_cases.rb +3 -3
- data/tracks/ruby/lib/{raindrop_cases.rb → raindrops_cases.rb} +1 -1
- data/tracks/rust/config.json +1 -0
- data/tracks/rust/exercises/atbash-cipher/Cargo.lock +4 -0
- data/tracks/rust/exercises/atbash-cipher/Cargo.toml +3 -0
- data/tracks/rust/exercises/atbash-cipher/example.rs +36 -0
- data/tracks/rust/exercises/atbash-cipher/tests/atbash-cipher.rs +82 -0
- data/tracks/rust/problems.md +1 -0
- data/tracks/scala/config.json +8 -0
- data/tracks/scala/exercises/sum-of-multiples/build.sbt +3 -0
- data/tracks/scala/exercises/sum-of-multiples/example.scala +10 -0
- data/tracks/scala/exercises/sum-of-multiples/src/main/scala/.keep +0 -0
- data/tracks/scala/exercises/sum-of-multiples/src/test/scala/SumOfMultiplesTest.scala +62 -0
- metadata +43 -23
- data/tracks/ruby/bin/generate-acronym +0 -7
- data/tracks/ruby/bin/generate-alphametics +0 -8
- data/tracks/ruby/bin/generate-binary +0 -7
- data/tracks/ruby/bin/generate-bracket-push +0 -7
- data/tracks/ruby/bin/generate-clock +0 -7
- data/tracks/ruby/bin/generate-connect +0 -7
- data/tracks/ruby/bin/generate-custom-set +0 -7
- data/tracks/ruby/bin/generate-difference-of-squares +0 -7
- data/tracks/ruby/bin/generate-gigasecond +0 -7
- data/tracks/ruby/bin/generate-hamming +0 -7
- data/tracks/ruby/bin/generate-hello-world +0 -7
- data/tracks/ruby/bin/generate-largest-series-product +0 -7
- data/tracks/ruby/bin/generate-leap +0 -7
- data/tracks/ruby/bin/generate-nth-prime +0 -7
- data/tracks/ruby/bin/generate-pangram +0 -7
- data/tracks/ruby/bin/generate-raindrops +0 -7
- data/tracks/ruby/bin/generate-rna-transcription +0 -7
- data/tracks/ruby/bin/generate-roman-numerals +0 -7
- data/tracks/ruby/bin/generate-run-length-encoding +0 -7
- data/tracks/ruby/bin/generate-two-bucket +0 -7
@@ -6,9 +6,10 @@
|
|
6
6
|
(defn- ->snake_case [s] (string/replace s \- \_))
|
7
7
|
|
8
8
|
(deftest check-exercises
|
9
|
-
(doseq [
|
10
|
-
:let [
|
11
|
-
|
12
|
-
|
13
|
-
(load-file (path-to-
|
14
|
-
(
|
9
|
+
(doseq [exercise ((json/parse-string (slurp "config.json")) "exercises")
|
10
|
+
:let [slug (exercise "slug")
|
11
|
+
path-to-exercise (partial str "exercises/" slug "/")
|
12
|
+
exercise-tests (symbol (str slug "-test"))]]
|
13
|
+
(load-file (path-to-exercise "src/example.clj"))
|
14
|
+
(load-file (path-to-exercise "test/" (->snake_case slug) "_test.clj"))
|
15
|
+
(is (successful? (run-tests exercise-tests)))))
|
data/tracks/clojure/config.json
CHANGED
@@ -3,59 +3,6 @@
|
|
3
3
|
"language": "Clojure",
|
4
4
|
"repository": "https://github.com/exercism/xclojure",
|
5
5
|
"active": true,
|
6
|
-
"problems": [
|
7
|
-
"hello-world",
|
8
|
-
"bob",
|
9
|
-
"rna-transcription",
|
10
|
-
"word-count",
|
11
|
-
"anagram",
|
12
|
-
"beer-song",
|
13
|
-
"nucleotide-count",
|
14
|
-
"hamming",
|
15
|
-
"phone-number",
|
16
|
-
"grade-school",
|
17
|
-
"robot-name",
|
18
|
-
"leap",
|
19
|
-
"etl",
|
20
|
-
"binary-search",
|
21
|
-
"meetup",
|
22
|
-
"space-age",
|
23
|
-
"grains",
|
24
|
-
"gigasecond",
|
25
|
-
"triangle",
|
26
|
-
"scrabble-score",
|
27
|
-
"roman-numerals",
|
28
|
-
"binary",
|
29
|
-
"trinary",
|
30
|
-
"prime-factors",
|
31
|
-
"raindrops",
|
32
|
-
"allergies",
|
33
|
-
"octal",
|
34
|
-
"strain",
|
35
|
-
"atbash-cipher",
|
36
|
-
"bank-account",
|
37
|
-
"crypto-square",
|
38
|
-
"pascals-triangle",
|
39
|
-
"sum-of-multiples",
|
40
|
-
"sieve",
|
41
|
-
"luhn",
|
42
|
-
"kindergarten-garden",
|
43
|
-
"robot-simulator",
|
44
|
-
"queen-attack",
|
45
|
-
"accumulate",
|
46
|
-
"binary-search-tree",
|
47
|
-
"difference-of-squares",
|
48
|
-
"hexadecimal",
|
49
|
-
"all-your-base",
|
50
|
-
"largest-series-product",
|
51
|
-
"pov",
|
52
|
-
"bracket-push",
|
53
|
-
"minesweeper",
|
54
|
-
"change",
|
55
|
-
"pangram",
|
56
|
-
"wordy",
|
57
|
-
"isogram"
|
58
|
-
],
|
59
6
|
"deprecated": [
|
60
7
|
|
61
8
|
],
|
@@ -66,5 +13,273 @@
|
|
66
13
|
"img"
|
67
14
|
],
|
68
15
|
"foregone": [
|
16
|
+
|
17
|
+
],
|
18
|
+
"exercises": [
|
19
|
+
{
|
20
|
+
"difficulty": 1,
|
21
|
+
"slug": "hello-world",
|
22
|
+
"topics": []
|
23
|
+
},
|
24
|
+
{
|
25
|
+
"difficulty": 1,
|
26
|
+
"slug": "bob",
|
27
|
+
"topics": []
|
28
|
+
},
|
29
|
+
{
|
30
|
+
"difficulty": 1,
|
31
|
+
"slug": "rna-transcription",
|
32
|
+
"topics": []
|
33
|
+
},
|
34
|
+
{
|
35
|
+
"difficulty": 1,
|
36
|
+
"slug": "word-count",
|
37
|
+
"topics": []
|
38
|
+
},
|
39
|
+
{
|
40
|
+
"difficulty": 1,
|
41
|
+
"slug": "anagram",
|
42
|
+
"topics": []
|
43
|
+
},
|
44
|
+
{
|
45
|
+
"difficulty": 1,
|
46
|
+
"slug": "beer-song",
|
47
|
+
"topics": []
|
48
|
+
},
|
49
|
+
{
|
50
|
+
"difficulty": 1,
|
51
|
+
"slug": "nucleotide-count",
|
52
|
+
"topics": []
|
53
|
+
},
|
54
|
+
{
|
55
|
+
"difficulty": 1,
|
56
|
+
"slug": "hamming",
|
57
|
+
"topics": []
|
58
|
+
},
|
59
|
+
{
|
60
|
+
"difficulty": 1,
|
61
|
+
"slug": "phone-number",
|
62
|
+
"topics": []
|
63
|
+
},
|
64
|
+
{
|
65
|
+
"difficulty": 1,
|
66
|
+
"slug": "grade-school",
|
67
|
+
"topics": []
|
68
|
+
},
|
69
|
+
{
|
70
|
+
"difficulty": 1,
|
71
|
+
"slug": "robot-name",
|
72
|
+
"topics": []
|
73
|
+
},
|
74
|
+
{
|
75
|
+
"difficulty": 1,
|
76
|
+
"slug": "leap",
|
77
|
+
"topics": []
|
78
|
+
},
|
79
|
+
{
|
80
|
+
"difficulty": 1,
|
81
|
+
"slug": "etl",
|
82
|
+
"topics": []
|
83
|
+
},
|
84
|
+
{
|
85
|
+
"difficulty": 1,
|
86
|
+
"slug": "flatten-array",
|
87
|
+
"topics": []
|
88
|
+
},
|
89
|
+
{
|
90
|
+
"difficulty": 1,
|
91
|
+
"slug": "binary-search",
|
92
|
+
"topics": []
|
93
|
+
},
|
94
|
+
{
|
95
|
+
"difficulty": 1,
|
96
|
+
"slug": "perfect-numbers",
|
97
|
+
"topics": []
|
98
|
+
},
|
99
|
+
{
|
100
|
+
"difficulty": 1,
|
101
|
+
"slug": "meetup",
|
102
|
+
"topics": []
|
103
|
+
},
|
104
|
+
{
|
105
|
+
"difficulty": 1,
|
106
|
+
"slug": "space-age",
|
107
|
+
"topics": []
|
108
|
+
},
|
109
|
+
{
|
110
|
+
"difficulty": 1,
|
111
|
+
"slug": "grains",
|
112
|
+
"topics": []
|
113
|
+
},
|
114
|
+
{
|
115
|
+
"difficulty": 1,
|
116
|
+
"slug": "gigasecond",
|
117
|
+
"topics": []
|
118
|
+
},
|
119
|
+
{
|
120
|
+
"difficulty": 1,
|
121
|
+
"slug": "triangle",
|
122
|
+
"topics": []
|
123
|
+
},
|
124
|
+
{
|
125
|
+
"difficulty": 1,
|
126
|
+
"slug": "scrabble-score",
|
127
|
+
"topics": []
|
128
|
+
},
|
129
|
+
{
|
130
|
+
"difficulty": 1,
|
131
|
+
"slug": "roman-numerals",
|
132
|
+
"topics": []
|
133
|
+
},
|
134
|
+
{
|
135
|
+
"difficulty": 1,
|
136
|
+
"slug": "binary",
|
137
|
+
"topics": []
|
138
|
+
},
|
139
|
+
{
|
140
|
+
"difficulty": 1,
|
141
|
+
"slug": "trinary",
|
142
|
+
"topics": []
|
143
|
+
},
|
144
|
+
{
|
145
|
+
"difficulty": 1,
|
146
|
+
"slug": "prime-factors",
|
147
|
+
"topics": []
|
148
|
+
},
|
149
|
+
{
|
150
|
+
"difficulty": 1,
|
151
|
+
"slug": "raindrops",
|
152
|
+
"topics": []
|
153
|
+
},
|
154
|
+
{
|
155
|
+
"difficulty": 1,
|
156
|
+
"slug": "allergies",
|
157
|
+
"topics": []
|
158
|
+
},
|
159
|
+
{
|
160
|
+
"difficulty": 1,
|
161
|
+
"slug": "octal",
|
162
|
+
"topics": []
|
163
|
+
},
|
164
|
+
{
|
165
|
+
"difficulty": 1,
|
166
|
+
"slug": "strain",
|
167
|
+
"topics": []
|
168
|
+
},
|
169
|
+
{
|
170
|
+
"difficulty": 1,
|
171
|
+
"slug": "atbash-cipher",
|
172
|
+
"topics": []
|
173
|
+
},
|
174
|
+
{
|
175
|
+
"difficulty": 1,
|
176
|
+
"slug": "bank-account",
|
177
|
+
"topics": []
|
178
|
+
},
|
179
|
+
{
|
180
|
+
"difficulty": 1,
|
181
|
+
"slug": "crypto-square",
|
182
|
+
"topics": []
|
183
|
+
},
|
184
|
+
{
|
185
|
+
"difficulty": 1,
|
186
|
+
"slug": "pascals-triangle",
|
187
|
+
"topics": []
|
188
|
+
},
|
189
|
+
{
|
190
|
+
"difficulty": 1,
|
191
|
+
"slug": "sum-of-multiples",
|
192
|
+
"topics": []
|
193
|
+
},
|
194
|
+
{
|
195
|
+
"difficulty": 1,
|
196
|
+
"slug": "sieve",
|
197
|
+
"topics": []
|
198
|
+
},
|
199
|
+
{
|
200
|
+
"difficulty": 1,
|
201
|
+
"slug": "luhn",
|
202
|
+
"topics": []
|
203
|
+
},
|
204
|
+
{
|
205
|
+
"difficulty": 1,
|
206
|
+
"slug": "kindergarten-garden",
|
207
|
+
"topics": []
|
208
|
+
},
|
209
|
+
{
|
210
|
+
"difficulty": 1,
|
211
|
+
"slug": "robot-simulator",
|
212
|
+
"topics": []
|
213
|
+
},
|
214
|
+
{
|
215
|
+
"difficulty": 1,
|
216
|
+
"slug": "queen-attack",
|
217
|
+
"topics": []
|
218
|
+
},
|
219
|
+
{
|
220
|
+
"difficulty": 1,
|
221
|
+
"slug": "accumulate",
|
222
|
+
"topics": []
|
223
|
+
},
|
224
|
+
{
|
225
|
+
"difficulty": 1,
|
226
|
+
"slug": "binary-search-tree",
|
227
|
+
"topics": []
|
228
|
+
},
|
229
|
+
{
|
230
|
+
"difficulty": 1,
|
231
|
+
"slug": "difference-of-squares",
|
232
|
+
"topics": []
|
233
|
+
},
|
234
|
+
{
|
235
|
+
"difficulty": 1,
|
236
|
+
"slug": "hexadecimal",
|
237
|
+
"topics": []
|
238
|
+
},
|
239
|
+
{
|
240
|
+
"difficulty": 1,
|
241
|
+
"slug": "all-your-base",
|
242
|
+
"topics": []
|
243
|
+
},
|
244
|
+
{
|
245
|
+
"difficulty": 1,
|
246
|
+
"slug": "largest-series-product",
|
247
|
+
"topics": []
|
248
|
+
},
|
249
|
+
{
|
250
|
+
"difficulty": 1,
|
251
|
+
"slug": "pov",
|
252
|
+
"topics": []
|
253
|
+
},
|
254
|
+
{
|
255
|
+
"difficulty": 1,
|
256
|
+
"slug": "bracket-push",
|
257
|
+
"topics": []
|
258
|
+
},
|
259
|
+
{
|
260
|
+
"difficulty": 1,
|
261
|
+
"slug": "minesweeper",
|
262
|
+
"topics": []
|
263
|
+
},
|
264
|
+
{
|
265
|
+
"difficulty": 1,
|
266
|
+
"slug": "change",
|
267
|
+
"topics": []
|
268
|
+
},
|
269
|
+
{
|
270
|
+
"difficulty": 1,
|
271
|
+
"slug": "pangram",
|
272
|
+
"topics": []
|
273
|
+
},
|
274
|
+
{
|
275
|
+
"difficulty": 1,
|
276
|
+
"slug": "wordy",
|
277
|
+
"topics": []
|
278
|
+
},
|
279
|
+
{
|
280
|
+
"difficulty": 1,
|
281
|
+
"slug": "isogram",
|
282
|
+
"topics": []
|
283
|
+
}
|
69
284
|
]
|
70
285
|
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
(ns flatten-array
|
2
|
+
(:refer-clojure :exclude [flatten]))
|
3
|
+
|
4
|
+
(defn flatten
|
5
|
+
"Flattens the given list and removes any nil values"
|
6
|
+
[coll]
|
7
|
+
(loop
|
8
|
+
[results nil
|
9
|
+
[elem & remaining] coll]
|
10
|
+
(if (or elem remaining)
|
11
|
+
(if (coll? elem)
|
12
|
+
(if (empty? elem)
|
13
|
+
(recur results remaining)
|
14
|
+
(recur results (conj remaining (rest elem) (first elem))))
|
15
|
+
(recur (conj results elem) remaining))
|
16
|
+
(reverse (remove nil? results)))))
|
@@ -0,0 +1,28 @@
|
|
1
|
+
(ns flatten-array-test
|
2
|
+
(require [clojure.test :refer [deftest is testing]]
|
3
|
+
[flatten-array]))
|
4
|
+
|
5
|
+
(deftest flattens-array-of-ints
|
6
|
+
(testing "flattens array with just integers present"
|
7
|
+
(is (= [1 2 3 4 5 6 7 8]
|
8
|
+
(flatten-array/flatten [1 [2 3 4 5 6 7] 8])))))
|
9
|
+
|
10
|
+
(deftest five-level-nesting
|
11
|
+
(testing "5 level nested list"
|
12
|
+
(is (= [0 2 2 3 8 100 4 50 -2]
|
13
|
+
(flatten-array/flatten [0 2 [[2 3] 8 100 4 [[[50]]]] -2])))))
|
14
|
+
|
15
|
+
(deftest six-level-nesting
|
16
|
+
(testing "6 level nested list"
|
17
|
+
(is (= [1 2 3 4 5 6 7 8]
|
18
|
+
(flatten-array/flatten [1 [2 [[3]] [4 [[5]]] 6 7] 8])))))
|
19
|
+
|
20
|
+
(deftest six-level-nested-with-nils
|
21
|
+
(testing "6 level nested list with nil values"
|
22
|
+
(is (= [0 2 2 3 8 100 -2]
|
23
|
+
(flatten-array/flatten [0 2 [[2 3] 8 [[100]] nil [[nil]]] -2])))))
|
24
|
+
|
25
|
+
(deftest all-nils-list
|
26
|
+
(testing "All values in nested list are nil"
|
27
|
+
(is (empty?
|
28
|
+
(flatten-array/flatten [nil [[[nil]]] nil nil [[nil nil] nil] nil])))))
|
@@ -0,0 +1,17 @@
|
|
1
|
+
(ns perfect-numbers)
|
2
|
+
|
3
|
+
(defn- get-divisors
|
4
|
+
"Utility function to get the divisors of a number"
|
5
|
+
[number]
|
6
|
+
(for [n (range 1 (inc (quot number 2))) :when (zero? (mod number n))]
|
7
|
+
n))
|
8
|
+
|
9
|
+
(defn classify [number]
|
10
|
+
"Classifies a positive integer as deficient, abundant or perfect"
|
11
|
+
(if-not (pos? number)
|
12
|
+
(throw (IllegalArgumentException. "Only positive numbers can be classified."))
|
13
|
+
(let [divisor-sum (apply + (get-divisors number))]
|
14
|
+
(cond
|
15
|
+
(> divisor-sum number) :abundant
|
16
|
+
(< divisor-sum number) :deficient
|
17
|
+
(= divisor-sum number) :perfect))))
|
@@ -0,0 +1,20 @@
|
|
1
|
+
(ns perfect-numbers-test
|
2
|
+
(:require
|
3
|
+
[clojure.test :refer [deftest testing is]]
|
4
|
+
[perfect-numbers]))
|
5
|
+
|
6
|
+
(deftest test-initialize-perfect-number
|
7
|
+
(testing "Negative numbers throw an exception"
|
8
|
+
(is (thrown? IllegalArgumentException (perfect-numbers/classify -1)))))
|
9
|
+
|
10
|
+
(deftest test-classify-deficient
|
11
|
+
(testing "13 is a deficient number"
|
12
|
+
(is (= :deficient (perfect-numbers/classify 13)))))
|
13
|
+
|
14
|
+
(deftest test-classify-perfect
|
15
|
+
(testing "28 is a perfect number"
|
16
|
+
(is (= :perfect (perfect-numbers/classify 28)))))
|
17
|
+
|
18
|
+
(deftest test-classify-abundant
|
19
|
+
(testing "12 is an abundant number"
|
20
|
+
(is (= :abundant (perfect-numbers/classify 12)))))
|
@@ -70,4 +70,11 @@ describe('School', () => {
|
|
70
70
|
expect(school.roster()).toEqual(expectedDb);
|
71
71
|
});
|
72
72
|
|
73
|
+
xit('roster cannot be modified outside of module using grade()', () => {
|
74
|
+
school.add('Aimee', 2);
|
75
|
+
school.grade(2).push('Oops.');
|
76
|
+
const expectedDb = { 2 : [ 'Aimee' ] };
|
77
|
+
expect(school.roster()).toEqual(expectedDb);
|
78
|
+
});
|
79
|
+
|
73
80
|
});
|
data/tracks/elixir/.travis.yml
CHANGED
@@ -16,5 +16,8 @@ script:
|
|
16
16
|
- EXERCISM_TEST_EXAMPLES=true elixirc --warnings-as-errors **/example.exs **/*_test.exs -o ./tmp > /dev/null
|
17
17
|
- rm -rf ./tmp
|
18
18
|
|
19
|
+
- bin/dialyzer_check.sh
|
20
|
+
|
19
21
|
- "! git grep ' $' -- \\*.exs | grep -v -e 'exercises/diamond/diamond_test.exs'"
|
22
|
+
|
20
23
|
sudo: false
|
@@ -0,0 +1,28 @@
|
|
1
|
+
mkdir -p ./tmp/src
|
2
|
+
mkdir ./tmp/build
|
3
|
+
|
4
|
+
|
5
|
+
for example_file in exercises/**/example.exs
|
6
|
+
do
|
7
|
+
exercise_dir=$(dirname $example_file)
|
8
|
+
exercise=$(basename $exercise_dir)
|
9
|
+
cp "$exercise_dir/example.exs" "./tmp/src/$exercise.exs"
|
10
|
+
done
|
11
|
+
|
12
|
+
elixirc -o ./tmp/build ./tmp/src/*.exs
|
13
|
+
|
14
|
+
if [ $CI ]; then
|
15
|
+
export PLT_FILENAME=elixir-${TRAVIS_ELIXIR_VERSION:=1.3.2}_${TRAVIS_OTP_RELEASE:=19.0}.plt
|
16
|
+
export PLT_LOCATION=./tmp/$PLT_FILENAME
|
17
|
+
wget -O $PLT_LOCATION https://github.com/danielberkompas/travis_elixir_plts/blob/master/elixir-${TRAVIS_ELIXIR_VERSION}_${TRAVIS_OTP_RELEASE}.plt?raw=true
|
18
|
+
|
19
|
+
dialyzer --no_check_plt --plt $PLT_LOCATION --no_native ./tmp/build;
|
20
|
+
RESULT=$?
|
21
|
+
else
|
22
|
+
dialyzer ./tmp/build;
|
23
|
+
RESULT=$?
|
24
|
+
fi
|
25
|
+
|
26
|
+
rm -rf ./tmp
|
27
|
+
|
28
|
+
exit $RESULT
|
data/tracks/elixir/config.json
CHANGED
@@ -66,7 +66,8 @@
|
|
66
66
|
"dot-dsl",
|
67
67
|
"custom-set",
|
68
68
|
"forth",
|
69
|
-
"pangram"
|
69
|
+
"pangram",
|
70
|
+
"clock"
|
70
71
|
],
|
71
72
|
"exercises": [
|
72
73
|
{
|
@@ -448,6 +449,17 @@
|
|
448
449
|
"Strings",
|
449
450
|
"Enumerations"
|
450
451
|
]
|
452
|
+
},
|
453
|
+
{
|
454
|
+
"slug": "clock",
|
455
|
+
"difficulty": 1,
|
456
|
+
"topics": [
|
457
|
+
"Protocols",
|
458
|
+
"Structs",
|
459
|
+
"Logic",
|
460
|
+
"Transforming",
|
461
|
+
"Integers"
|
462
|
+
]
|
451
463
|
}
|
452
464
|
],
|
453
465
|
"deprecated": [
|
data/tracks/elixir/docs/TESTS.md
CHANGED
@@ -31,3 +31,84 @@ Or, you can enable all the tests by commenting out the
|
|
31
31
|
```elixir
|
32
32
|
# ExUnit.configure exclude: :pending, trace: true
|
33
33
|
```
|
34
|
+
|
35
|
+
### Typespecs and Dialyzer (DIscrepancy AnalYZer for ERlang programs)
|
36
|
+
|
37
|
+
Elixir exercises include a skeleton implementation file. This
|
38
|
+
file outlines the module and functions that you are expected
|
39
|
+
to implement. In most exercises, you will find typespecs
|
40
|
+
above the function declaration. These start with the `@spec` tag and
|
41
|
+
typically follow the `@spec function_name(type1, type2) :: return_type`
|
42
|
+
format. These are used in Elixir and Erlang as documentation and
|
43
|
+
in conjunction with a tool called Dialyzer to find type inconsistencies
|
44
|
+
and possible bugs. For more information see the
|
45
|
+
[Elixir typespecs guide](http://elixir-lang.org/getting-started/typespecs-and-behaviours.html)
|
46
|
+
or the [typespecs documentation](http://elixir-lang.org/docs/stable/elixir/typespecs.html). For
|
47
|
+
documentation about Dialyzer see [Erlang -- dialyzer](http://erlang.org/doc/man/dialyzer.html).
|
48
|
+
|
49
|
+
Optionally, you may want to check
|
50
|
+
the types of your implementation with Dialyzer. There are a couple
|
51
|
+
of steps you will need to take. Because all of the Elixir exercises
|
52
|
+
are implemented as `.exs` script files they will not create a
|
53
|
+
`.beam` file when they are dynamically compiled when running
|
54
|
+
normal tests. In order to create the `.beam` file that Dialyzer
|
55
|
+
needs to analyze run:
|
56
|
+
|
57
|
+
```bash
|
58
|
+
$ elixirc word_count.exs
|
59
|
+
```
|
60
|
+
|
61
|
+
This will create a file called `Elixir.Words.beam`. Now you can run
|
62
|
+
Dialyzer on your implementation with:
|
63
|
+
|
64
|
+
```bash
|
65
|
+
$ dialyzer Elixir.Words.beam
|
66
|
+
|
67
|
+
Checking whether the PLT ~/.dialyzer_plt is up-to-date... yes
|
68
|
+
Proceeding with analysis...
|
69
|
+
done in 0m0.27s
|
70
|
+
done (passed successfully)
|
71
|
+
```
|
72
|
+
|
73
|
+
If this is the first time you have run Dialyzer you
|
74
|
+
will most likely not have a `plt` file. The persistent lookup table,
|
75
|
+
or PLT is used by Dialyzer to cache information about built in Elixir
|
76
|
+
and Erlang types. To create a plt with sensible defaults run:
|
77
|
+
|
78
|
+
|
79
|
+
```bash
|
80
|
+
$ dialyzer --build_plt --apps erts kernel stdlib crypto public_key /path/to/elixir
|
81
|
+
```
|
82
|
+
|
83
|
+
Make sure to change the path to your system's path to the Elixir libraries. For
|
84
|
+
instance, if you installed Elixir with homebrew you will probably find it under
|
85
|
+
`/usr/local/Cellar/elixir/1.3.2`.
|
86
|
+
|
87
|
+
It should be reiterated that running Dialyzer and removing all warnings
|
88
|
+
is an optional step when completing an exercise. Dialyzer warnings can
|
89
|
+
be difficult to decipher. For instance, examine the warnings for this very silly
|
90
|
+
implementation of the `Bob` exercise.
|
91
|
+
|
92
|
+
```elixir
|
93
|
+
defmodule Bob do
|
94
|
+
@spec hey(input :: String.t) :: String.t
|
95
|
+
def hey(input) do
|
96
|
+
1
|
97
|
+
end
|
98
|
+
|
99
|
+
def hey(input) do
|
100
|
+
end
|
101
|
+
end
|
102
|
+
```
|
103
|
+
|
104
|
+
This produces the following warnings.
|
105
|
+
|
106
|
+
```bash
|
107
|
+
bob.exs:2: Invalid type specification for function 'Elixir.Bob':hey/1. The success typing is (_) -> 1
|
108
|
+
bob.exs:7: The variable _input@1 can never match since previous clauses completely covered the type any()
|
109
|
+
```
|
110
|
+
|
111
|
+
The first warning means that the function is not returning
|
112
|
+
the correct type. The last indicates that the second function
|
113
|
+
definition can never be reached because the first function
|
114
|
+
definition always matches.
|
@@ -17,6 +17,11 @@ defmodule BinarySearchTest do
|
|
17
17
|
assert BinarySearch.search({2, 4, 6}, 3) == :not_found
|
18
18
|
end
|
19
19
|
|
20
|
+
@tag :pending
|
21
|
+
test "returns :not_found when key is too high" do
|
22
|
+
assert BinarySearch.search({2, 4, 6}, 9) == :not_found
|
23
|
+
end
|
24
|
+
|
20
25
|
@tag :pending
|
21
26
|
test "finds key in a tuple with a single item" do
|
22
27
|
assert BinarySearch.search({3}, 3) == {:ok, 0}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
defmodule Clock do
|
2
|
+
defstruct hour: 0, minute: 0
|
3
|
+
|
4
|
+
@doc """
|
5
|
+
Returns a string representation of a clock:
|
6
|
+
|
7
|
+
iex> Clock.new(8, 9) |> to_string
|
8
|
+
"08:09"
|
9
|
+
"""
|
10
|
+
@spec new(integer, integer) :: Clock
|
11
|
+
def new(hour, minute) do
|
12
|
+
end
|
13
|
+
|
14
|
+
@doc """
|
15
|
+
Adds two clock times:
|
16
|
+
|
17
|
+
iex> Clock.add(10, 0) |> Clock.add(3) |> to_string
|
18
|
+
"10:03"
|
19
|
+
"""
|
20
|
+
@spec add(Clock, integer) :: Clock
|
21
|
+
def add(%Clock{hour: hour, minute: minute}, add_minute) do
|
22
|
+
end
|
23
|
+
end
|