trackler 2.0.6.40 → 2.0.6.41
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/common/exercises/book-store/canonical-data.json +7 -1
- data/common/exercises/rotational-cipher/{cannonical-data.json → canonical-data.json} +0 -0
- data/lib/trackler/version.rb +1 -1
- data/tracks/c/config.json +9 -0
- data/tracks/c/exercises/triangle/makefile +16 -0
- data/tracks/c/exercises/triangle/src/example.c +33 -0
- data/tracks/c/exercises/triangle/src/example.h +15 -0
- data/tracks/c/exercises/triangle/src/triangle.h +10 -0
- data/tracks/c/exercises/triangle/test/test_triangle.c +121 -0
- data/tracks/c/exercises/triangle/test/vendor/unity.c +1300 -0
- data/tracks/c/exercises/triangle/test/vendor/unity.h +274 -0
- data/tracks/c/exercises/triangle/test/vendor/unity_internals.h +701 -0
- data/tracks/clojure/.gitignore +1 -0
- data/tracks/clojure/_src/clock_generator.clj +5 -0
- data/tracks/clojure/_src/generator.clj +72 -0
- data/tracks/clojure/config.json +6 -0
- data/tracks/clojure/exercises/clock/clock.mustache +34 -0
- data/tracks/clojure/exercises/clock/project.clj +4 -0
- data/tracks/clojure/exercises/clock/src/example.clj +19 -0
- data/tracks/clojure/exercises/clock/test/clock_test.clj +177 -0
- data/tracks/clojure/project.clj +4 -1
- data/tracks/csharp/exercises/poker/Example.cs +1 -1
- data/tracks/csharp/exercises/poker/PokerTest.cs +10 -0
- data/tracks/erlang/docs/INSTALLATION.md +14 -3
- data/tracks/erlang/docs/LEARNING.md +1 -0
- data/tracks/go/exercises/gigasecond/gigasecond_test.go +5 -2
- data/tracks/go/exercises/grade-school/example.go +2 -0
- data/tracks/go/exercises/grade-school/grade_school_test.go +8 -0
- data/tracks/go/exercises/hamming/hamming_test.go +1 -1
- data/tracks/go/exercises/hello-world/hello_test.go +6 -4
- data/tracks/haskell/exercises/accumulate/src/Accumulate.hs +1 -1
- data/tracks/haskell/exercises/anagram/src/Anagram.hs +1 -1
- data/tracks/java/bin/journey-test.sh +21 -4
- data/tracks/java/exercises/allergies/src/example/java/Allergen.java +20 -0
- data/tracks/java/exercises/hamming/src/test/java/HammingTest.java +10 -3
- data/tracks/java/exercises/luhn/src/example/java/LuhnValidator.java +19 -11
- data/tracks/java/exercises/luhn/src/test/java/LuhnValidatorTest.java +43 -1
- data/tracks/java/exercises/meetup/src/example/java/MeetupSchedule.java +8 -0
- data/tracks/java/exercises/meetup/src/test/java/MeetupTest.java +91 -91
- data/tracks/java/exercises/perfect-numbers/src/example/java/Classification.java +5 -0
- data/tracks/java/exercises/robot-simulator/src/example/java/GridPosition.java +29 -0
- data/tracks/java/exercises/robot-simulator/src/example/java/Orientation.java +5 -0
- data/tracks/java/exercises/secret-handshake/src/example/java/Signal.java +5 -0
- data/tracks/java/exercises/sublist/src/example/java/Relationship.java +5 -0
- data/tracks/java/exercises/triangle/src/example/java/TriangleException.java +5 -0
- data/tracks/java/exercises/triangle/src/example/java/TriangleKind.java +5 -0
- data/tracks/julia/config.json +10 -1
- data/tracks/julia/exercises/atbash-cipher/runtests.jl +36 -36
- data/tracks/julia/exercises/pangram/example.jl +2 -0
- data/tracks/julia/exercises/pangram/pangram.jl +4 -0
- data/tracks/julia/exercises/pangram/runtests.jl +40 -0
- data/tracks/perl5/exercises/bob/Example.pm +1 -1
- data/tracks/perl5/exercises/bob/bob.t +27 -31
- data/tracks/php/exercises/accumulate/accumulate_test.php +1 -1
- data/tracks/php/exercises/acronym/acronym_test.php +1 -1
- data/tracks/php/exercises/allergies/allergies_test.php +1 -1
- data/tracks/php/exercises/anagram/anagram_test.php +1 -1
- data/tracks/php/exercises/atbash-cipher/atbash-cipher_test.php +1 -1
- data/tracks/php/exercises/beer-song/beer-song_test.php +1 -1
- data/tracks/php/exercises/binary/binary_test.php +2 -2
- data/tracks/php/exercises/bob/bob_test.php +1 -1
- data/tracks/php/exercises/book-store/book-store_test.php +1 -1
- data/tracks/php/exercises/bowling/bowling_test.php +1 -1
- data/tracks/php/exercises/bracket-push/bracket-push_test.php +1 -1
- data/tracks/php/exercises/change/change_test.php +3 -3
- data/tracks/php/exercises/clock/clock_test.php +1 -1
- data/tracks/php/exercises/connect/connect_test.php +1 -1
- data/tracks/php/exercises/difference-of-squares/difference-of-squares_test.php +1 -1
- data/tracks/php/exercises/etl/etl_test.php +1 -1
- data/tracks/php/exercises/gigasecond/gigasecond_test.php +1 -1
- data/tracks/php/exercises/grains/grains_test.php +1 -1
- data/tracks/php/exercises/hamming/hamming_test.php +2 -2
- data/tracks/php/exercises/hello-world/hello-world_test.php +1 -1
- data/tracks/php/exercises/isogram/isogram_test.php +1 -1
- data/tracks/php/exercises/largest-series-product/largest-series-product_test.php +1 -1
- data/tracks/php/exercises/leap/leap_test.php +1 -1
- data/tracks/php/exercises/markdown/markdown_test.php +1 -1
- data/tracks/php/exercises/minesweeper/minesweeper_test.php +7 -7
- data/tracks/php/exercises/nucleotide-count/nucleotide-count_test.php +1 -1
- data/tracks/php/exercises/ocr-numbers/ocr-numbers_test.php +1 -1
- data/tracks/php/exercises/pangram/pangram_test.php +1 -1
- data/tracks/php/exercises/phone-number/phone-number_test.php +1 -1
- data/tracks/php/exercises/pig-latin/pig-latin_test.php +1 -1
- data/tracks/php/exercises/raindrops/raindrops_test.php +1 -1
- data/tracks/php/exercises/rna-transcription/rna-transcription_test.php +1 -1
- data/tracks/php/exercises/robot-name/robot-name_test.php +1 -1
- data/tracks/php/exercises/robot-simulator/robot-simulator_test.php +1 -1
- data/tracks/php/exercises/roman-numerals/roman-numerals_test.php +1 -1
- data/tracks/php/exercises/sieve/sieve_test.php +1 -1
- data/tracks/php/exercises/space-age/space-age_test.php +1 -1
- data/tracks/php/exercises/triangle/triangle_test.php +1 -1
- data/tracks/php/exercises/trinary/trinary_test.php +1 -1
- data/tracks/php/exercises/variable-length-quantity/variable-length-quantity_test.php +3 -3
- data/tracks/php/exercises/word-count/word-count_test.php +1 -1
- data/tracks/php/exercises/wordy/wordy_test.php +3 -3
- data/tracks/python/config.json +3 -13
- data/tracks/python/exercises/rectangles/rectangles_count_test.py +15 -22
- data/tracks/scala/config.json +684 -665
- data/tracks/scala/exercises/binary-search/build.sbt +3 -0
- data/tracks/scala/exercises/binary-search/example.scala +23 -0
- data/tracks/scala/exercises/binary-search/src/main/scala/BinarySearch.scala +0 -0
- data/tracks/scala/exercises/binary-search/src/test/scala/BinarySearchTest.scala +63 -0
- data/tracks/scala/exercises/strain/build.sbt +3 -0
- data/tracks/scala/exercises/strain/example.scala +22 -0
- data/tracks/scala/exercises/strain/src/main/scala/Strain.scala +0 -0
- data/tracks/scala/exercises/strain/src/test/scala/StrainTest.scala +78 -0
- data/tracks/scala/testgen/src/main/scala/AllYourBaseTestGenerator.scala +13 -20
- data/tracks/scala/testgen/src/main/scala/BinarySearchTestGenerator.scala +48 -0
- data/tracks/scala/testgen/src/main/scala/BowlingTestGenerator.scala +24 -32
- data/tracks/scala/testgen/src/main/scala/CustomSetTestGenerator.scala +148 -112
- data/tracks/scala/testgen/src/main/scala/TestBuilder.scala +86 -0
- metadata +30 -3
- data/tracks/java/exercises/allergies/src/example/java/Allergen.java +0 -1
- data/tracks/java/exercises/meetup/src/example/java/MeetupSchedule.java +0 -1
- data/tracks/java/exercises/perfect-numbers/src/example/java/Classification.java +0 -1
- data/tracks/java/exercises/robot-simulator/src/example/java/GridPosition.java +0 -1
- data/tracks/java/exercises/robot-simulator/src/example/java/Orientation.java +0 -1
- data/tracks/java/exercises/secret-handshake/src/example/java/Signal.java +0 -1
- data/tracks/java/exercises/sublist/src/example/java/Relationship.java +0 -1
- data/tracks/java/exercises/triangle/src/example/java/TriangleException.java +0 -1
- data/tracks/java/exercises/triangle/src/example/java/TriangleKind.java +0 -1
data/tracks/clojure/.gitignore
CHANGED
@@ -0,0 +1,72 @@
|
|
1
|
+
(ns generator
|
2
|
+
(:require [cheshire.core :as json]
|
3
|
+
[clojure.java.shell :refer [sh]]
|
4
|
+
[clojure.java.io :refer [reader]]
|
5
|
+
[stencil.core :as stencil])
|
6
|
+
(:import (java.io File IOException)))
|
7
|
+
|
8
|
+
(defn file-exists?
|
9
|
+
"Helper function to determine if a given file exists."
|
10
|
+
[path]
|
11
|
+
(.exists (File. path)))
|
12
|
+
|
13
|
+
(defn warn-and-exit
|
14
|
+
"Wrapper function to warn with the given message and then exit with a non-zero return"
|
15
|
+
[message]
|
16
|
+
(println message)
|
17
|
+
(System/exit 1))
|
18
|
+
|
19
|
+
(defn clone-test-data
|
20
|
+
"Clone the x-common repo from github"
|
21
|
+
[]
|
22
|
+
(sh "git" "clone" "git@github.com:exercism/x-common"))
|
23
|
+
|
24
|
+
(defn load-test-data
|
25
|
+
"Clones and loads the test data for the given exercise"
|
26
|
+
[exercise-name]
|
27
|
+
(when-not (file-exists? "x-common")
|
28
|
+
(clone-test-data))
|
29
|
+
(let [test-data-filename (format "x-common/exercises/%s/canonical-data.json" exercise-name)]
|
30
|
+
(when-not (file-exists? test-data-filename)
|
31
|
+
(warn-and-exit
|
32
|
+
(format "Could not find test data for %s (looking in %s)"
|
33
|
+
exercise-name test-data-filename)))
|
34
|
+
(json/parse-stream (reader test-data-filename))))
|
35
|
+
|
36
|
+
(defn munge-test-data
|
37
|
+
"Loads the generator namespace for the exercise and calls the munge-data function on the given test-data."
|
38
|
+
[exercise-name test-data]
|
39
|
+
(let [exercise-ns (symbol (str exercise-name "-generator"))]
|
40
|
+
(try
|
41
|
+
(require [exercise-ns])
|
42
|
+
(if-let [munge-data-fn (ns-resolve exercise-ns (symbol "munge-data"))]
|
43
|
+
(munge-data-fn test-data)
|
44
|
+
(do
|
45
|
+
(println (format "No munge-data function defined in %s" exercise-ns))
|
46
|
+
(println (format "Skipping any munging of canonical-data for %s" exercise-name))
|
47
|
+
test-data))
|
48
|
+
(catch IOException e
|
49
|
+
(println (format "Could not require %s due to an exception:\n\t%s" exercise-ns (.getMessage e)))
|
50
|
+
(println (format "Skipping any munging of canonical-data for %s" exercise-name))
|
51
|
+
test-data))))
|
52
|
+
|
53
|
+
(defn generate-test-data
|
54
|
+
"Munges the test-data and renders the test for the exercise using the test template."
|
55
|
+
[exercise-name test-template-path test-data]
|
56
|
+
(let [munged-test-data (munge-test-data exercise-name test-data)
|
57
|
+
template (slurp test-template-path)]
|
58
|
+
(spit
|
59
|
+
(format "exercises/%s/test/%s_test.clj" exercise-name exercise-name)
|
60
|
+
(stencil/render-string template munged-test-data))))
|
61
|
+
|
62
|
+
(defn -main
|
63
|
+
"Uses the test template for the exercise and test data to generate test cases."
|
64
|
+
[exercise-name & args]
|
65
|
+
(let [test-template-path (format "exercises/%s/%s.mustache" exercise-name exercise-name)
|
66
|
+
test-data (load-test-data exercise-name)]
|
67
|
+
(if (file-exists? test-template-path)
|
68
|
+
(do
|
69
|
+
(generate-test-data exercise-name test-template-path test-data)
|
70
|
+
(println (format "Generated tests for %s exercise using template %s" exercise-name test-template-path)))
|
71
|
+
(warn-and-exit (format "No exercise test template found at '%s'" test-template-path))))
|
72
|
+
(shutdown-agents))
|
data/tracks/clojure/config.json
CHANGED
@@ -7,6 +7,7 @@
|
|
7
7
|
|
8
8
|
],
|
9
9
|
"ignored": [
|
10
|
+
"_src",
|
10
11
|
"_test",
|
11
12
|
"docs",
|
12
13
|
"target",
|
@@ -61,6 +62,11 @@
|
|
61
62
|
"slug": "phone-number",
|
62
63
|
"topics": []
|
63
64
|
},
|
65
|
+
{
|
66
|
+
"difficulty": 1,
|
67
|
+
"slug": "clock",
|
68
|
+
"topics": []
|
69
|
+
},
|
64
70
|
{
|
65
71
|
"difficulty": 1,
|
66
72
|
"slug": "grade-school",
|
@@ -0,0 +1,34 @@
|
|
1
|
+
(ns clock-test
|
2
|
+
(:require [clock :refer :all]
|
3
|
+
[clojure.test :refer [deftest testing is]]))
|
4
|
+
|
5
|
+
(deftest create-clock-test
|
6
|
+
{{#create}}
|
7
|
+
{{#cases}}
|
8
|
+
|
9
|
+
(testing "{{{description}}}"
|
10
|
+
(let [test-clock (clock->string (clock {{{hour}}} {{{minute}}}))]
|
11
|
+
(is (= test-clock "{{{expected}}}")))){{/cases}}{{/create}})
|
12
|
+
|
13
|
+
(deftest add-time-test
|
14
|
+
{{#add}}
|
15
|
+
{{#cases}}
|
16
|
+
|
17
|
+
(testing "{{{description}}}"
|
18
|
+
(let [test-clock (clock->string (add-time (clock {{{hour}}} {{{minute}}}) {{{add}}}))]
|
19
|
+
(is (= test-clock "{{{expected}}}")))){{/cases}}{{/add}})
|
20
|
+
|
21
|
+
(deftest equal-clock-test
|
22
|
+
{{#equal}}
|
23
|
+
{{#cases}}
|
24
|
+
(testing "{{{description}}}"
|
25
|
+
(let [{{#clock1}}clock1 (clock {{{hour}}} {{{minute}}}){{/clock1}}
|
26
|
+
{{#clock2}}clock2 (clock {{{hour}}} {{{minute}}}){{/clock2}}]
|
27
|
+
{{#expected}}
|
28
|
+
(is (= clock1 clock2))))
|
29
|
+
{{/expected}}
|
30
|
+
{{^expected}}
|
31
|
+
(is (not= clock1 clock2))))
|
32
|
+
{{/expected}}
|
33
|
+
{{/cases}}
|
34
|
+
{{/equal}})
|
@@ -0,0 +1,19 @@
|
|
1
|
+
(ns clock)
|
2
|
+
|
3
|
+
(defn clock
|
4
|
+
"Return a 24 hour clock representation of the given hours and minutes."
|
5
|
+
[in-hour in-minute]
|
6
|
+
(let [total-minutes (mod (+ (* in-hour 60) in-minute) (* 60 24))
|
7
|
+
hours (mod (quot total-minutes 60) 24)
|
8
|
+
minutes (mod total-minutes 60)]
|
9
|
+
{:hour hours :minute minutes}))
|
10
|
+
|
11
|
+
(defn clock->string
|
12
|
+
"Print the HH:MM representation of a clock."
|
13
|
+
[in-clock]
|
14
|
+
(format "%02d:%02d" (:hour in-clock) (:minute in-clock)))
|
15
|
+
|
16
|
+
(defn add-time
|
17
|
+
"Add minutes to the given clock."
|
18
|
+
[in-clock minutes-to-add]
|
19
|
+
(clock (:hour in-clock) (+ (:minute in-clock) minutes-to-add)))
|
@@ -0,0 +1,177 @@
|
|
1
|
+
(ns clock-test
|
2
|
+
(:require [clock :refer :all]
|
3
|
+
[clojure.test :refer [deftest testing is]]))
|
4
|
+
|
5
|
+
(deftest create-clock-test
|
6
|
+
|
7
|
+
(testing "on the hour"
|
8
|
+
(let [test-clock (clock->string (clock 8 0))]
|
9
|
+
(is (= test-clock "08:00"))))
|
10
|
+
(testing "past the hour"
|
11
|
+
(let [test-clock (clock->string (clock 11 9))]
|
12
|
+
(is (= test-clock "11:09"))))
|
13
|
+
(testing "midnight is zero hours"
|
14
|
+
(let [test-clock (clock->string (clock 24 0))]
|
15
|
+
(is (= test-clock "00:00"))))
|
16
|
+
(testing "hour rolls over"
|
17
|
+
(let [test-clock (clock->string (clock 25 0))]
|
18
|
+
(is (= test-clock "01:00"))))
|
19
|
+
(testing "hour rolls over continuously"
|
20
|
+
(let [test-clock (clock->string (clock 100 0))]
|
21
|
+
(is (= test-clock "04:00"))))
|
22
|
+
(testing "sixty minutes is next hour"
|
23
|
+
(let [test-clock (clock->string (clock 1 60))]
|
24
|
+
(is (= test-clock "02:00"))))
|
25
|
+
(testing "minutes roll over"
|
26
|
+
(let [test-clock (clock->string (clock 0 160))]
|
27
|
+
(is (= test-clock "02:40"))))
|
28
|
+
(testing "minutes roll over continuously"
|
29
|
+
(let [test-clock (clock->string (clock 0 1723))]
|
30
|
+
(is (= test-clock "04:43"))))
|
31
|
+
(testing "hour and minutes roll over"
|
32
|
+
(let [test-clock (clock->string (clock 25 160))]
|
33
|
+
(is (= test-clock "03:40"))))
|
34
|
+
(testing "hour and minutes roll over continuously"
|
35
|
+
(let [test-clock (clock->string (clock 201 3001))]
|
36
|
+
(is (= test-clock "11:01"))))
|
37
|
+
(testing "hour and minutes roll over to exactly midnight"
|
38
|
+
(let [test-clock (clock->string (clock 72 8640))]
|
39
|
+
(is (= test-clock "00:00"))))
|
40
|
+
(testing "negative hour"
|
41
|
+
(let [test-clock (clock->string (clock -1 15))]
|
42
|
+
(is (= test-clock "23:15"))))
|
43
|
+
(testing "negative hour rolls over"
|
44
|
+
(let [test-clock (clock->string (clock -25 0))]
|
45
|
+
(is (= test-clock "23:00"))))
|
46
|
+
(testing "negative hour rolls over continuously"
|
47
|
+
(let [test-clock (clock->string (clock -91 0))]
|
48
|
+
(is (= test-clock "05:00"))))
|
49
|
+
(testing "negative minutes"
|
50
|
+
(let [test-clock (clock->string (clock 1 -40))]
|
51
|
+
(is (= test-clock "00:20"))))
|
52
|
+
(testing "negative minutes roll over"
|
53
|
+
(let [test-clock (clock->string (clock 1 -160))]
|
54
|
+
(is (= test-clock "22:20"))))
|
55
|
+
(testing "negative minutes roll over continuously"
|
56
|
+
(let [test-clock (clock->string (clock 1 -4820))]
|
57
|
+
(is (= test-clock "16:40"))))
|
58
|
+
(testing "negative hour and minutes both roll over"
|
59
|
+
(let [test-clock (clock->string (clock -25 -160))]
|
60
|
+
(is (= test-clock "20:20"))))
|
61
|
+
(testing "negative hour and minutes both roll over continuously"
|
62
|
+
(let [test-clock (clock->string (clock -121 -5810))]
|
63
|
+
(is (= test-clock "22:10")))))
|
64
|
+
|
65
|
+
(deftest add-time-test
|
66
|
+
|
67
|
+
(testing "add minutes"
|
68
|
+
(let [test-clock (clock->string (add-time (clock 10 0) 3))]
|
69
|
+
(is (= test-clock "10:03"))))
|
70
|
+
(testing "add no minutes"
|
71
|
+
(let [test-clock (clock->string (add-time (clock 6 41) 0))]
|
72
|
+
(is (= test-clock "06:41"))))
|
73
|
+
(testing "add to next hour"
|
74
|
+
(let [test-clock (clock->string (add-time (clock 0 45) 40))]
|
75
|
+
(is (= test-clock "01:25"))))
|
76
|
+
(testing "add more than one hour"
|
77
|
+
(let [test-clock (clock->string (add-time (clock 10 0) 61))]
|
78
|
+
(is (= test-clock "11:01"))))
|
79
|
+
(testing "add more than two hours with carry"
|
80
|
+
(let [test-clock (clock->string (add-time (clock 0 45) 160))]
|
81
|
+
(is (= test-clock "03:25"))))
|
82
|
+
(testing "add across midnight"
|
83
|
+
(let [test-clock (clock->string (add-time (clock 23 59) 2))]
|
84
|
+
(is (= test-clock "00:01"))))
|
85
|
+
(testing "add more than one day (1500 min = 25 hrs)"
|
86
|
+
(let [test-clock (clock->string (add-time (clock 5 32) 1500))]
|
87
|
+
(is (= test-clock "06:32"))))
|
88
|
+
(testing "add more than two days"
|
89
|
+
(let [test-clock (clock->string (add-time (clock 1 1) 3500))]
|
90
|
+
(is (= test-clock "11:21"))))
|
91
|
+
(testing "subtract minutes"
|
92
|
+
(let [test-clock (clock->string (add-time (clock 10 3) -3))]
|
93
|
+
(is (= test-clock "10:00"))))
|
94
|
+
(testing "subtract to previous hour"
|
95
|
+
(let [test-clock (clock->string (add-time (clock 10 3) -30))]
|
96
|
+
(is (= test-clock "09:33"))))
|
97
|
+
(testing "subtract more than an hour"
|
98
|
+
(let [test-clock (clock->string (add-time (clock 10 3) -70))]
|
99
|
+
(is (= test-clock "08:53"))))
|
100
|
+
(testing "subtract across midnight"
|
101
|
+
(let [test-clock (clock->string (add-time (clock 0 3) -4))]
|
102
|
+
(is (= test-clock "23:59"))))
|
103
|
+
(testing "subtract more than two hours"
|
104
|
+
(let [test-clock (clock->string (add-time (clock 0 0) -160))]
|
105
|
+
(is (= test-clock "21:20"))))
|
106
|
+
(testing "subtract more than two hours with borrow"
|
107
|
+
(let [test-clock (clock->string (add-time (clock 6 15) -160))]
|
108
|
+
(is (= test-clock "03:35"))))
|
109
|
+
(testing "subtract more than one day (1500 min = 25 hrs)"
|
110
|
+
(let [test-clock (clock->string (add-time (clock 5 32) -1500))]
|
111
|
+
(is (= test-clock "04:32"))))
|
112
|
+
(testing "subtract more than two days"
|
113
|
+
(let [test-clock (clock->string (add-time (clock 2 20) -3000))]
|
114
|
+
(is (= test-clock "00:20")))))
|
115
|
+
|
116
|
+
(deftest equal-clock-test
|
117
|
+
(testing "clocks with same time"
|
118
|
+
(let [clock1 (clock 15 37)
|
119
|
+
clock2 (clock 15 37)]
|
120
|
+
(is (= clock1 clock2))))
|
121
|
+
(testing "clocks a minute apart"
|
122
|
+
(let [clock1 (clock 15 36)
|
123
|
+
clock2 (clock 15 37)]
|
124
|
+
(is (not= clock1 clock2))))
|
125
|
+
(testing "clocks an hour apart"
|
126
|
+
(let [clock1 (clock 14 37)
|
127
|
+
clock2 (clock 15 37)]
|
128
|
+
(is (not= clock1 clock2))))
|
129
|
+
(testing "clocks with hour overflow"
|
130
|
+
(let [clock1 (clock 10 37)
|
131
|
+
clock2 (clock 34 37)]
|
132
|
+
(is (= clock1 clock2))))
|
133
|
+
(testing "clocks with hour overflow by several days"
|
134
|
+
(let [clock1 (clock 3 11)
|
135
|
+
clock2 (clock 99 11)]
|
136
|
+
(is (= clock1 clock2))))
|
137
|
+
(testing "clocks with negative hour"
|
138
|
+
(let [clock1 (clock 22 40)
|
139
|
+
clock2 (clock -2 40)]
|
140
|
+
(is (= clock1 clock2))))
|
141
|
+
(testing "clocks with negative hour that wraps"
|
142
|
+
(let [clock1 (clock 17 3)
|
143
|
+
clock2 (clock -31 3)]
|
144
|
+
(is (= clock1 clock2))))
|
145
|
+
(testing "clocks with negative hour that wraps multiple times"
|
146
|
+
(let [clock1 (clock 13 49)
|
147
|
+
clock2 (clock -83 49)]
|
148
|
+
(is (= clock1 clock2))))
|
149
|
+
(testing "clocks with minute overflow"
|
150
|
+
(let [clock1 (clock 0 1)
|
151
|
+
clock2 (clock 0 1441)]
|
152
|
+
(is (= clock1 clock2))))
|
153
|
+
(testing "clocks with minute overflow by several days"
|
154
|
+
(let [clock1 (clock 2 2)
|
155
|
+
clock2 (clock 2 4322)]
|
156
|
+
(is (= clock1 clock2))))
|
157
|
+
(testing "clocks with negative minute"
|
158
|
+
(let [clock1 (clock 2 40)
|
159
|
+
clock2 (clock 3 -20)]
|
160
|
+
(is (= clock1 clock2))))
|
161
|
+
(testing "clocks with negative minute that wraps"
|
162
|
+
(let [clock1 (clock 4 10)
|
163
|
+
clock2 (clock 5 -1490)]
|
164
|
+
(is (= clock1 clock2))))
|
165
|
+
(testing "clocks with negative minute that wraps multiple times"
|
166
|
+
(let [clock1 (clock 6 15)
|
167
|
+
clock2 (clock 6 -4305)]
|
168
|
+
(is (= clock1 clock2))))
|
169
|
+
(testing "clocks with negative hours and minutes"
|
170
|
+
(let [clock1 (clock 7 32)
|
171
|
+
clock2 (clock -12 -268)]
|
172
|
+
(is (= clock1 clock2))))
|
173
|
+
(testing "clocks with negative hours and minutes that wrap"
|
174
|
+
(let [clock1 (clock 18 7)
|
175
|
+
clock2 (clock -54 -11513)]
|
176
|
+
(is (= clock1 clock2))))
|
177
|
+
)
|
data/tracks/clojure/project.clj
CHANGED
@@ -2,5 +2,8 @@
|
|
2
2
|
:description "Exercism Exercises in Clojure"
|
3
3
|
:url "https://github.com/exercism/xclojure"
|
4
4
|
:test-paths ["_test"]
|
5
|
+
:source-paths ["_src"]
|
6
|
+
:aliases {"generate" ["run" "-m" "generator"]}
|
5
7
|
:dependencies [[org.clojure/clojure "1.8.0"]
|
6
|
-
[cheshire "5.5.0"]
|
8
|
+
[cheshire "5.5.0"]
|
9
|
+
[stencil "0.5.0"]])
|
@@ -168,4 +168,14 @@ public class PokerTest
|
|
168
168
|
Assert.That(Poker.BestHands(new[] { spadeStraightTo9, diamondStraightTo9, threeOf4 }),
|
169
169
|
Is.EqualTo(new[] { spadeStraightTo9, diamondStraightTo9 }));
|
170
170
|
}
|
171
|
+
|
172
|
+
[Ignore("Remove to run test")]
|
173
|
+
[Test]
|
174
|
+
public void Straight_to_5_against_a_pair_of_jacks()
|
175
|
+
{
|
176
|
+
const string straightTo5 = "2S 4D 5C 3S AS";
|
177
|
+
const string twoJacks = "JD 8D 7D JC 5D";
|
178
|
+
Assert.That(Poker.BestHands(new[] { straightTo5, twoJacks }),
|
179
|
+
Is.EqualTo(new[] { straightTo5 }));
|
180
|
+
}
|
171
181
|
}
|
@@ -1,3 +1,6 @@
|
|
1
|
+
If you have any trouble installing erlang please consider joining the
|
2
|
+
[gitter support channel](https://gitter.im/exercism/xerlang)
|
3
|
+
|
1
4
|
### Homebrew for Mac OS X
|
2
5
|
|
3
6
|
Update your Homebrew to latest:
|
@@ -18,8 +21,15 @@ via `brew` are welcome).
|
|
18
21
|
|
19
22
|
### On Linux
|
20
23
|
|
21
|
-
Fedora 17+ and Fedora Rawhide: `sudo yum -y install erlang`
|
22
|
-
Arch Linux
|
24
|
+
* Fedora 17+ and Fedora Rawhide: `sudo yum -y install erlang`
|
25
|
+
* Arch Linux: Erlang is available on AUR via `yaourt -S erlang`
|
26
|
+
* Ubuntu/Debian: `sudo apt-get install erlang`
|
27
|
+
|
28
|
+
It may happen that the packages above are dated. At least for ubuntu 16.04
|
29
|
+
it should still be able to run the tests. If your package gets to old (older
|
30
|
+
than OTP 17.0) please consider a build from source or using [`kerl`](https://github.com/kerl/kerl)
|
31
|
+
or [`asdf-vm`](https://github.com/asdf-vm/asdf) and [`asdf-erlang`](https://github.com/asdf-vm/asdf-erlang)
|
32
|
+
instead (follow installation instructions in the corresponding repositories).
|
23
33
|
|
24
34
|
Also fetch the latest `rebar3` from rebar3.org and put it somewhere in
|
25
35
|
your `$PATH` and make it executable. (PRs that describe this better or
|
@@ -37,4 +47,5 @@ choco install rebar3
|
|
37
47
|
|
38
48
|
### Installing from Source
|
39
49
|
|
40
|
-
Get [Erlang OTP
|
50
|
+
Get [a recent Erlang OTP](http://www.erlang.org/download.html) and follow their
|
51
|
+
[build-instructions](https://github.com/erlang/otp/blob/maint/HOWTO/INSTALL.md).
|
@@ -1,5 +1,6 @@
|
|
1
1
|
Exercism provides exercises and feedback but can be difficult to jump into for those learning Erlang for the first time. These resources can help you get started:
|
2
2
|
|
3
|
+
* [Exercism related BEAM support channel on gitter](https://gitter.im/exercism/xerlang)
|
3
4
|
* [Erlang Documentation](http://www.erlang.org/doc.html)
|
4
5
|
* [Learn You Some Erlang for Great Good](http://learnyousomeerlang.com)
|
5
6
|
* [StackOverflow](http://stackoverflow.com/)
|
@@ -16,10 +16,13 @@ const (
|
|
16
16
|
fmtDT = "2006-01-02T15:04:05"
|
17
17
|
)
|
18
18
|
|
19
|
-
func
|
19
|
+
func TestTestVersion(t *testing.T) {
|
20
20
|
if testVersion != targetTestVersion {
|
21
|
-
t.Fatalf("Found testVersion = %v, want %v
|
21
|
+
t.Fatalf("Found testVersion = %v, want %v", testVersion, targetTestVersion)
|
22
22
|
}
|
23
|
+
}
|
24
|
+
|
25
|
+
func TestAddGigasecond(t *testing.T) {
|
23
26
|
for _, tc := range addCases {
|
24
27
|
in := parse(tc.in, t)
|
25
28
|
want := parse(tc.want, t)
|
@@ -19,6 +19,14 @@ import (
|
|
19
19
|
"testing"
|
20
20
|
)
|
21
21
|
|
22
|
+
const targetTestVersion = 1
|
23
|
+
|
24
|
+
func TestTestVersion(t *testing.T) {
|
25
|
+
if testVersion != targetTestVersion {
|
26
|
+
t.Fatalf("Found testVersion = %v, want %v", testVersion, targetTestVersion)
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
22
30
|
func TestNewSchoolIsEmpty(t *testing.T) {
|
23
31
|
if len(New().Enrollment()) != 0 {
|
24
32
|
t.Error("New school not empty")
|
@@ -6,7 +6,7 @@ const targetTestVersion = 5
|
|
6
6
|
|
7
7
|
func TestTestVersion(t *testing.T) {
|
8
8
|
if testVersion != targetTestVersion {
|
9
|
-
t.
|
9
|
+
t.Fatalf("Found testVersion = %v, want %v.", testVersion, targetTestVersion)
|
10
10
|
}
|
11
11
|
}
|
12
12
|
|
@@ -9,6 +9,12 @@ import "testing"
|
|
9
9
|
|
10
10
|
const targetTestVersion = 3
|
11
11
|
|
12
|
+
func TestTestVersion(t *testing.T) {
|
13
|
+
if testVersion != targetTestVersion {
|
14
|
+
t.Fatalf("Found testVersion = %v, want %v", testVersion, targetTestVersion)
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
12
18
|
func TestHelloWorld(t *testing.T) {
|
13
19
|
tests := []struct {
|
14
20
|
name, expected string
|
@@ -22,8 +28,4 @@ func TestHelloWorld(t *testing.T) {
|
|
22
28
|
t.Fatalf("HelloWorld(%s) = %v, want %v", test.name, observed, test.expected)
|
23
29
|
}
|
24
30
|
}
|
25
|
-
|
26
|
-
if testVersion != targetTestVersion {
|
27
|
-
t.Fatalf("Found testVersion = %v, want %v", testVersion, targetTestVersion)
|
28
|
-
}
|
29
31
|
}
|
@@ -72,6 +72,8 @@ get_operating_system() {
|
|
72
72
|
echo "linux";;
|
73
73
|
(Windows*)
|
74
74
|
echo "windows";;
|
75
|
+
(MINGW*)
|
76
|
+
echo "windows";;
|
75
77
|
(*)
|
76
78
|
echo "linux";;
|
77
79
|
esac
|
@@ -102,10 +104,25 @@ download_exercism_cli() {
|
|
102
104
|
# "curl..." :: HTTP 302 headers, including "Location" -- URL to redirect to.
|
103
105
|
# "awk..." :: pluck last path segment from "Location" (i.e. the version number)
|
104
106
|
local version="$(curl --head --silent ${latest} | awk -v FS=/ '/Location:/{print $NF}' | tr -d '\r')"
|
105
|
-
|
107
|
+
|
108
|
+
local download_url_suffix
|
109
|
+
local unzip_command
|
110
|
+
local unzip_from_file_option
|
111
|
+
if [[ ${os} == "windows" ]] ; then
|
112
|
+
download_url_suffix="zip"
|
113
|
+
unzip_command="unzip -d"
|
114
|
+
unzip_from_file_option=""
|
115
|
+
else
|
116
|
+
download_url_suffix="tgz"
|
117
|
+
unzip_command="tar xz -C"
|
118
|
+
unzip_from_file_option="-f"
|
119
|
+
fi
|
120
|
+
local download_url=${CLI_RELEASES}/download/${version}/exercism-${os}-${arch}.${download_url_suffix}
|
106
121
|
|
107
122
|
mkdir -p ${exercism_home}
|
108
|
-
|
123
|
+
local temp=`mktemp`
|
124
|
+
curl -s --location ${download_url} > ${temp}
|
125
|
+
${unzip_command} ${exercism_home} ${unzip_from_file_option} ${temp}
|
109
126
|
echo "<<< download_exercism_cli()"
|
110
127
|
}
|
111
128
|
|
@@ -192,8 +209,8 @@ solve_all_exercises() {
|
|
192
209
|
|
193
210
|
local xjava=$( pwd )
|
194
211
|
local exercism_cli="./exercism --config ${exercism_configfile}"
|
195
|
-
local exercises=`cat config.json | jq '.
|
196
|
-
local total_exercises=`cat config.json | jq '.
|
212
|
+
local exercises=`cat config.json | jq '.exercises[].slug + " "' --join-output`
|
213
|
+
local total_exercises=`cat config.json | jq '.exercises | length'`
|
197
214
|
local current_exercise_number=1
|
198
215
|
local tempfile="${TMPDIR:-/tmp}/journey-test.sh-unignore_all_tests.txt"
|
199
216
|
|
@@ -0,0 +1,20 @@
|
|
1
|
+
public enum Allergen {
|
2
|
+
EGGS(1),
|
3
|
+
PEANUTS(2),
|
4
|
+
SHELLFISH(4),
|
5
|
+
STRAWBERRIES(8),
|
6
|
+
TOMATOES(16),
|
7
|
+
CHOCOLATE(32),
|
8
|
+
POLLEN(64),
|
9
|
+
CATS(128);
|
10
|
+
|
11
|
+
private final int score;
|
12
|
+
|
13
|
+
Allergen(int score) {
|
14
|
+
this.score = score;
|
15
|
+
}
|
16
|
+
|
17
|
+
public int getScore() {
|
18
|
+
return score;
|
19
|
+
}
|
20
|
+
}
|
@@ -3,10 +3,15 @@ import static org.junit.Assert.*;
|
|
3
3
|
|
4
4
|
import org.junit.Test;
|
5
5
|
import org.junit.Ignore;
|
6
|
+
import org.junit.Rule;
|
7
|
+
import org.junit.rules.ExpectedException;
|
6
8
|
|
7
9
|
public class HammingTest {
|
8
10
|
|
9
11
|
|
12
|
+
@Rule
|
13
|
+
public ExpectedException thrown = ExpectedException.none();
|
14
|
+
|
10
15
|
@Test
|
11
16
|
public void testNoDifferenceBetweenIdenticalStrands() {
|
12
17
|
assertThat(Hamming.compute("A", "A"), is(0));
|
@@ -37,14 +42,16 @@ public class HammingTest {
|
|
37
42
|
}
|
38
43
|
|
39
44
|
@Ignore
|
40
|
-
@Test
|
45
|
+
@Test
|
41
46
|
public void testValidatesFirstStrandNotLonger() {
|
42
|
-
|
47
|
+
thrown.expect(IllegalArgumentException.class);
|
48
|
+
Hamming.compute("AAAG", "AAA");
|
43
49
|
}
|
44
50
|
|
45
51
|
@Ignore
|
46
|
-
@Test
|
52
|
+
@Test
|
47
53
|
public void testValidatesOtherStrandNotLonger() {
|
54
|
+
thrown.expect(IllegalArgumentException.class);
|
48
55
|
Hamming.compute("AAA", "AAAG");
|
49
56
|
}
|
50
57
|
|
@@ -9,10 +9,17 @@ final class LuhnValidator {
|
|
9
9
|
boolean isValid(final String candidate) {
|
10
10
|
final String sanitizedCandidate = SPACE_PATTERN.matcher(candidate).replaceAll("");
|
11
11
|
|
12
|
+
if (sanitizedCandidate.length() <= 1) {
|
13
|
+
return false;
|
14
|
+
}
|
15
|
+
|
16
|
+
// We need to alter every second digit counting from the right. Reversing makes this easy!
|
17
|
+
final String reversedSanitizedCandidate = reverse(sanitizedCandidate);
|
18
|
+
|
12
19
|
final List<Integer> computedDigits = new ArrayList<>();
|
13
20
|
|
14
|
-
for (int charIndex = 0; charIndex <
|
15
|
-
int inputDigit = Character.digit(
|
21
|
+
for (int charIndex = 0; charIndex < reversedSanitizedCandidate.length(); charIndex++) {
|
22
|
+
int inputDigit = Character.digit(reversedSanitizedCandidate.charAt(charIndex), 10);
|
16
23
|
|
17
24
|
/*
|
18
25
|
* Character.digit returns a negative int if the supplied character does not represent a digit with respect
|
@@ -23,21 +30,22 @@ final class LuhnValidator {
|
|
23
30
|
}
|
24
31
|
|
25
32
|
if (charIndex % 2 == 1) {
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
* is equivalent to applying the modulo operation below universally.
|
32
|
-
*/
|
33
|
-
inputDigit = (2 * inputDigit) % 9;
|
33
|
+
inputDigit = 2 * inputDigit;
|
34
|
+
|
35
|
+
if (inputDigit > 9) {
|
36
|
+
inputDigit -= 9;
|
37
|
+
}
|
34
38
|
}
|
35
39
|
|
36
40
|
computedDigits.add(inputDigit);
|
37
41
|
}
|
38
42
|
|
39
43
|
final int digitSum = computedDigits.stream().mapToInt(Integer::intValue).sum();
|
40
|
-
return digitSum
|
44
|
+
return digitSum % 10 == 0;
|
45
|
+
}
|
46
|
+
|
47
|
+
private String reverse(final String string) {
|
48
|
+
return new StringBuilder(string).reverse().toString();
|
41
49
|
}
|
42
50
|
|
43
51
|
}
|