trackler 2.2.1.43 → 2.2.1.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/trackler/version.rb +1 -1
- data/problem-specifications/exercises/lens-person/description.md +1 -1
- data/problem-specifications/exercises/palindrome-products/description.md +5 -12
- data/problem-specifications/exercises/pascals-triangle/canonical-data.json +1 -7
- data/tracks/c/exercises/meetup/src/example.c +64 -60
- data/tracks/c/exercises/meetup/src/example.h +2 -2
- data/tracks/c/exercises/meetup/test/test_meetup.c +4 -4
- data/tracks/cfml/config.json +179 -169
- data/tracks/cfml/exercises/markdown/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/markdown/Markdown.cfc +121 -0
- data/tracks/cfml/exercises/markdown/MarkdownTest.cfc +51 -0
- data/tracks/cfml/exercises/markdown/Solution.cfc +204 -0
- data/tracks/cfml/exercises/markdown/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/markdown/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/markdown/box.json +8 -0
- data/tracks/cfml/exercises/markdown/index.cfm +37 -0
- data/tracks/csharp/exercises/dominoes/DominoesTest.cs +40 -45
- data/tracks/csharp/exercises/meetup/MeetupTest.cs +761 -83
- data/tracks/csharp/generators/Exercises/Dominoes.cs +33 -0
- data/tracks/csharp/generators/Exercises/Meetup.cs +46 -0
- data/tracks/csharp/generators/Output/FormattingExtensions.cs +11 -1
- data/tracks/csharp/generators/Output/TypesExtensions.cs +23 -0
- data/tracks/csharp/generators/Output/ValueFormatter.cs +70 -69
- data/tracks/dart/config.json +15 -3
- data/tracks/dart/exercises/word-count/README.md +18 -0
- data/tracks/dart/exercises/word-count/lib/example.dart +26 -0
- data/tracks/dart/exercises/word-count/lib/word_count.dart +3 -0
- data/tracks/dart/exercises/word-count/pubspec.lock +293 -0
- data/tracks/dart/exercises/word-count/pubspec.yaml +3 -0
- data/tracks/dart/exercises/word-count/test/word_count_test.dart +64 -0
- data/tracks/ecmascript/docs/INSTALLATION.md +4 -7
- data/tracks/elixir/exercises/hello-world/README.md +1 -26
- data/tracks/elixir/exercises/hello-world/example.exs +3 -7
- data/tracks/elixir/exercises/hello-world/hello_world.exs +3 -25
- data/tracks/elixir/exercises/hello-world/hello_world_test.exs +2 -13
- data/tracks/elixir/mix.lock +1 -1
- data/tracks/elm/config.json +11 -0
- data/tracks/elm/exercises/pascals-triangle/README.md +51 -0
- data/tracks/elm/exercises/pascals-triangle/Triangle.elm +1 -0
- data/tracks/elm/exercises/pascals-triangle/Triangle.example.elm +23 -0
- data/tracks/elm/exercises/pascals-triangle/elm-package.json +14 -0
- data/tracks/elm/exercises/pascals-triangle/package.json +14 -0
- data/tracks/elm/exercises/pascals-triangle/tests/Tests.elm +34 -0
- data/tracks/elm/exercises/pascals-triangle/tests/elm-package.json +16 -0
- data/tracks/fsharp/exercises/grade-school/GradeSchool.fs +2 -2
- data/tracks/fsharp/exercises/grade-school/GradeSchoolTest.fs +3 -2
- data/tracks/java/CONTRIBUTING.md +34 -0
- data/tracks/java/config.json +42 -6
- data/tracks/java/exercises/largest-series-product/src/main/java/LargestSeriesProductCalculator.java +7 -3
- data/tracks/java/exercises/matrix/src/main/java/Matrix.java +23 -0
- data/tracks/julia/config.json +11 -2
- data/tracks/julia/exercises/grains/README.md +33 -0
- data/tracks/julia/exercises/grains/example.jl +23 -0
- data/tracks/julia/exercises/grains/grains.jl +9 -0
- data/tracks/julia/exercises/grains/runtests.jl +27 -0
- data/tracks/lua/README.md +1 -1
- data/tracks/mips/exercises/octal/README.md +3 -8
- data/tracks/ocaml/exercises/palindrome-products/README.md +8 -14
- data/tracks/perl6/.travis.yml +7 -3
- data/tracks/perl6/bin/exercise-gen.pl6 +5 -1
- data/tracks/perl6/exercises/accumulate/README.md +0 -3
- data/tracks/perl6/exercises/accumulate/accumulate.t +9 -3
- data/tracks/perl6/exercises/all-your-base/README.md +1 -1
- data/tracks/perl6/exercises/all-your-base/all-your-base.t +23 -11
- data/tracks/perl6/exercises/all-your-base/example.yaml +1 -1
- data/tracks/perl6/exercises/allergies/README.md +0 -1
- data/tracks/perl6/exercises/allergies/allergies.t +22 -10
- data/tracks/perl6/exercises/anagram/anagram.t +22 -10
- data/tracks/perl6/exercises/atbash-cipher/README.md +2 -1
- data/tracks/perl6/exercises/atbash-cipher/atbash-cipher.t +22 -10
- data/tracks/perl6/exercises/binary/README.md +2 -0
- data/tracks/perl6/exercises/bob/bob.t +24 -11
- data/tracks/perl6/exercises/bob/example.yaml +2 -2
- data/tracks/perl6/exercises/clock/clock.t +22 -10
- data/tracks/perl6/exercises/flatten-array/README.md +1 -2
- data/tracks/perl6/exercises/flatten-array/example.yaml +1 -1
- data/tracks/perl6/exercises/flatten-array/flatten-array.t +23 -11
- data/tracks/perl6/exercises/grade-school/README.md +0 -1
- data/tracks/perl6/exercises/grade-school/grade-school.t +9 -3
- data/tracks/perl6/exercises/grains/README.md +0 -1
- data/tracks/perl6/exercises/grains/grains.t +22 -10
- data/tracks/perl6/exercises/hello-world/example.yaml +3 -3
- data/tracks/perl6/exercises/hello-world/hello-world.t +25 -12
- data/tracks/perl6/exercises/leap/README.md +1 -1
- data/tracks/perl6/exercises/leap/example.yaml +1 -1
- data/tracks/perl6/exercises/leap/leap.t +23 -11
- data/tracks/perl6/exercises/linked-list/README.md +10 -10
- data/tracks/perl6/exercises/linked-list/linked-list.t +9 -3
- data/tracks/perl6/exercises/luhn/README.md +7 -7
- data/tracks/perl6/exercises/luhn/luhn.t +22 -10
- data/tracks/perl6/exercises/phone-number/README.md +3 -2
- data/tracks/perl6/exercises/phone-number/phone-number.t +22 -10
- data/tracks/perl6/exercises/raindrops/raindrops.t +22 -10
- data/tracks/perl6/exercises/rna-transcription/rna-transcription.t +22 -10
- data/tracks/perl6/exercises/robot-name/robot-name.t +9 -3
- data/tracks/perl6/exercises/scrabble-score/README.md +3 -1
- data/tracks/perl6/exercises/scrabble-score/scrabble-score.t +22 -10
- data/tracks/perl6/exercises/space-age/README.md +2 -1
- data/tracks/perl6/exercises/space-age/space-age.t +22 -10
- data/tracks/perl6/exercises/trinary/README.md +1 -1
- data/tracks/perl6/exercises/word-count/README.md +1 -2
- data/tracks/perl6/exercises/word-count/word-count.t +22 -10
- data/tracks/perl6/exercises/wordy/README.md +0 -5
- data/tracks/perl6/exercises/wordy/wordy.t +22 -10
- data/tracks/perl6/templates/test.mustache +26 -15
- data/tracks/python/config.json +10 -0
- data/tracks/python/exercises/book-store/book_store.py +1 -1
- data/tracks/python/exercises/flatten-array/flatten_array.py +1 -1
- data/tracks/python/exercises/matrix/matrix.py +1 -1
- data/tracks/python/exercises/palindrome-products/palindrome_products.py +2 -2
- data/tracks/python/exercises/perfect-numbers/perfect_numbers.py +2 -2
- data/tracks/python/exercises/pythagorean-triplet/pythagorean_triplet.py +3 -3
- data/tracks/python/exercises/raindrops/raindrops.py +1 -1
- data/tracks/python/exercises/scale-generator/scale_generator.py +1 -1
- data/tracks/python/exercises/sieve/sieve.py +1 -1
- data/tracks/python/exercises/sublist/sublist.py +1 -1
- data/tracks/python/exercises/transpose/transpose.py +1 -1
- data/tracks/python/exercises/triangle/triangle.py +4 -1
- data/tracks/python/exercises/two-bucket/example.py +59 -0
- data/tracks/python/exercises/two-bucket/two_bucket.py +2 -0
- data/tracks/python/exercises/two-bucket/two_bucket_test.py +32 -0
- data/tracks/scheme/config.json +59 -89
- data/tracks/scheme/config/maintainers.json +11 -11
- data/tracks/sml/exercises/allergies/README.md +20 -5
- data/tracks/sml/exercises/allergies/allergies.sml +11 -14
- data/tracks/sml/exercises/allergies/example.sml +9 -9
- data/tracks/sml/exercises/allergies/test.sml +65 -129
- data/tracks/sml/exercises/allergies/testlib.sml +159 -0
- data/tracks/sml/exercises/hamming/README.md +21 -5
- data/tracks/sml/exercises/hamming/example.sml +14 -10
- data/tracks/sml/exercises/hamming/hamming.sml +4 -3
- data/tracks/sml/exercises/hamming/test.sml +55 -64
- data/tracks/sml/exercises/hamming/testlib.sml +159 -0
- data/tracks/typescript/config.json +15 -0
- data/tracks/typescript/exercises/linked-list/linked-list.test.ts +11 -11
- data/tracks/typescript/exercises/nth-prime/README.md +36 -0
- data/tracks/typescript/exercises/nth-prime/nth-prime.example.ts +28 -0
- data/tracks/typescript/exercises/nth-prime/nth-prime.test.ts +25 -0
- data/tracks/typescript/exercises/nth-prime/nth-prime.ts +0 -0
- data/tracks/typescript/exercises/nth-prime/package.json +36 -0
- data/tracks/typescript/exercises/nth-prime/tsconfig.json +22 -0
- data/tracks/typescript/exercises/nth-prime/tslint.json +127 -0
- data/tracks/typescript/exercises/nth-prime/yarn.lock +2305 -0
- data/tracks/typescript/exercises/prime-factors/README.md +1 -1
- data/tracks/typescript/exercises/prime-factors/prime-factors.test.ts +11 -11
- data/tracks/typescript/exercises/series/README.md +1 -1
- data/tracks/typescript/exercises/series/series.test.ts +11 -11
- data/tracks/typescript/img/icon.png +0 -0
- data/tracks/typescript/img/icon.svg +3 -8
- metadata +44 -2
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
datatype allergen = Eggs
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
| Peanuts
|
|
3
|
+
| Shellfish
|
|
4
|
+
| Strawberries
|
|
5
|
+
| Tomatoes
|
|
6
|
+
| Chocolate
|
|
7
|
+
| Pollen
|
|
8
|
+
| Cats
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
raise Fail "'list' has not been implemented"
|
|
10
|
+
fun allergicTo (score: int) (a: allergen) : bool =
|
|
11
|
+
raise Fail "'allergicTo' is not implemented"
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
fun allergic_to (code: int) (a: allergen): bool =
|
|
17
|
-
raise Fail "'allergic_to' has not been implemented"
|
|
13
|
+
fun list (score: int): allergen list =
|
|
14
|
+
raise Fail "'list' is not implemented"
|
|
@@ -25,12 +25,12 @@ fun valueOf a =
|
|
|
25
25
|
| Cats => 7
|
|
26
26
|
|
|
27
27
|
(* allergic_to = fn : int -> allergen -> bool
|
|
28
|
-
Given a
|
|
29
|
-
represented by the
|
|
28
|
+
Given a score (integer) and an allergen returns true if the person
|
|
29
|
+
represented by the score is allergic to the specified allergen
|
|
30
30
|
*)
|
|
31
|
-
fun
|
|
32
|
-
let fun testAllergy
|
|
33
|
-
let val codeWord = Word.fromInt(
|
|
31
|
+
fun allergicTo score a =
|
|
32
|
+
let fun testAllergy score n =
|
|
33
|
+
let val codeWord = Word.fromInt(score)
|
|
34
34
|
val nWord = Word.fromInt(n)
|
|
35
35
|
val oneWord = Word.fromInt(1)
|
|
36
36
|
in (* ((code >> n) & 1) == 1 *)
|
|
@@ -40,12 +40,12 @@ fun allergic_to code a =
|
|
|
40
40
|
)
|
|
41
41
|
end
|
|
42
42
|
in
|
|
43
|
-
testAllergy
|
|
43
|
+
testAllergy score (valueOf a)
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
(* allergies = fn: int -> allergen list
|
|
47
|
-
Given a
|
|
47
|
+
Given a score that represents a person's allergies
|
|
48
48
|
return a list of all allergens that they are allergic to
|
|
49
49
|
*)
|
|
50
|
-
fun list
|
|
51
|
-
List.filter (
|
|
50
|
+
fun list score =
|
|
51
|
+
List.filter (allergicTo score) [Eggs, Peanuts, Shellfish, Strawberries, Tomatoes, Chocolate, Pollen, Cats]
|
|
@@ -1,132 +1,68 @@
|
|
|
1
|
+
(* version 1.0.0 *)
|
|
2
|
+
|
|
3
|
+
use "testlib.sml";
|
|
1
4
|
use "allergies.sml";
|
|
2
5
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
input = 20,
|
|
64
|
-
expected = [Shellfish, Tomatoes]
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
description = "Code = 192 returns allergen list of [Pollen, Cats]",
|
|
68
|
-
input = 192,
|
|
69
|
-
expected = [Pollen, Cats]
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
description = "Code = 255 returns all allergens",
|
|
73
|
-
input = 255,
|
|
74
|
-
expected = [Eggs, Peanuts, Shellfish, Strawberries,Tomatoes, Chocolate, Pollen, Cats]
|
|
75
|
-
}
|
|
76
|
-
],
|
|
77
|
-
allergic_to = [
|
|
78
|
-
{
|
|
79
|
-
description = "Code = 1 is allergic to Eggs",
|
|
80
|
-
input = 1,
|
|
81
|
-
allergen = Eggs,
|
|
82
|
-
expected = true
|
|
83
|
-
},
|
|
84
|
-
{
|
|
85
|
-
description = "Code = 1 is not allergic to Pollen",
|
|
86
|
-
input = 1,
|
|
87
|
-
allergen = Pollen,
|
|
88
|
-
expected = false
|
|
89
|
-
},
|
|
90
|
-
{
|
|
91
|
-
description = "Code = 2 is allergic to Peanuts",
|
|
92
|
-
input = 2,
|
|
93
|
-
allergen = Peanuts,
|
|
94
|
-
expected = true
|
|
95
|
-
},
|
|
96
|
-
{
|
|
97
|
-
description = "Code = 255 is allergic to Cats",
|
|
98
|
-
input = 255,
|
|
99
|
-
allergen = Cats,
|
|
100
|
-
expected = true
|
|
101
|
-
}
|
|
6
|
+
infixr |>
|
|
7
|
+
fun x |> f = f x
|
|
8
|
+
|
|
9
|
+
val testsuite =
|
|
10
|
+
describe "allergies" [
|
|
11
|
+
describe "allergicTo" [
|
|
12
|
+
describe "no allergies means not allergic" [
|
|
13
|
+
test "is not allergic to Peanuts"
|
|
14
|
+
(fn _ => allergicTo 0 Peanuts |> Expect.falsy),
|
|
15
|
+
|
|
16
|
+
test "is not allergic to Cats"
|
|
17
|
+
(fn _ => allergicTo 0 Cats |> Expect.falsy),
|
|
18
|
+
|
|
19
|
+
test "is not allergic to Strawberries"
|
|
20
|
+
(fn _ => allergicTo 0 Strawberries |> Expect.falsy)
|
|
21
|
+
],
|
|
22
|
+
|
|
23
|
+
test "is allergic to eggs"
|
|
24
|
+
(fn _ => allergicTo 1 Eggs |> Expect.truthy),
|
|
25
|
+
|
|
26
|
+
describe "allergic to eggs in addition to other stuff" [
|
|
27
|
+
test "is allergic to Eggs"
|
|
28
|
+
(fn _ => allergicTo 5 Eggs |> Expect.truthy),
|
|
29
|
+
|
|
30
|
+
test "is allergic to Shellfish"
|
|
31
|
+
(fn _ => allergicTo 5 Shellfish |> Expect.truthy),
|
|
32
|
+
|
|
33
|
+
test "is allergic to Strawberries"
|
|
34
|
+
(fn _ => allergicTo 5 Strawberries |> Expect.falsy)
|
|
35
|
+
]
|
|
36
|
+
],
|
|
37
|
+
|
|
38
|
+
describe "list" [
|
|
39
|
+
test "no allergies at all"
|
|
40
|
+
(fn _ => list (0) |> Expect.equalTo []),
|
|
41
|
+
|
|
42
|
+
test "allergic to just eggs"
|
|
43
|
+
(fn _ => list (1) |> Expect.equalTo [Eggs]),
|
|
44
|
+
|
|
45
|
+
test "allergic to just peanuts"
|
|
46
|
+
(fn _ => list (2) |> Expect.equalTo [Peanuts]),
|
|
47
|
+
|
|
48
|
+
test "allergic to just strawberries"
|
|
49
|
+
(fn _ => list (8) |> Expect.equalTo [Strawberries]),
|
|
50
|
+
|
|
51
|
+
test "allergic to eggs and peanuts"
|
|
52
|
+
(fn _ => list (3) |> Expect.equalTo [Eggs, Peanuts]),
|
|
53
|
+
|
|
54
|
+
test "allergic to more than eggs but not peanuts"
|
|
55
|
+
(fn _ => list (5) |> Expect.equalTo [Eggs, Shellfish]),
|
|
56
|
+
|
|
57
|
+
test "allergic to lots of stuff"
|
|
58
|
+
(fn _ => list (248) |> Expect.equalTo [Strawberries, Tomatoes, Chocolate, Pollen, Cats]),
|
|
59
|
+
|
|
60
|
+
test "allergic to everything"
|
|
61
|
+
(fn _ => list (255) |> Expect.equalTo [Eggs, Peanuts, Shellfish, Strawberries, Tomatoes, Chocolate, Pollen, Cats]),
|
|
62
|
+
|
|
63
|
+
test "ignore non allergen score parts"
|
|
64
|
+
(fn _ => list (509) |> Expect.equalTo [Eggs, Shellfish, Strawberries, Tomatoes, Chocolate, Pollen, Cats])
|
|
65
|
+
]
|
|
102
66
|
]
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
fun run_tests _ [] = []
|
|
106
|
-
| run_tests f (x :: xs) =
|
|
107
|
-
let
|
|
108
|
-
fun aux { description, is_correct } =
|
|
109
|
-
let
|
|
110
|
-
val expl = description ^ ": " ^
|
|
111
|
-
(if is_correct then "PASSED" else "FAILED") ^ "\n"
|
|
112
|
-
in
|
|
113
|
-
(print (expl); is_correct)
|
|
114
|
-
end
|
|
115
|
-
in
|
|
116
|
-
(aux x) :: run_tests f xs
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
fun evaluateList f { description, input, expected } =
|
|
120
|
-
{ description = description, is_correct = (f input) = expected }
|
|
121
|
-
|
|
122
|
-
fun evaluateAllergicTo f { description, input, allergen, expected } =
|
|
123
|
-
{ description = description, is_correct = (f input allergen) = expected }
|
|
124
|
-
|
|
125
|
-
val testResults = run_tests list (List.map (evaluateList list) (#list test_cases))
|
|
126
|
-
@ run_tests list (List.map (evaluateAllergicTo allergic_to) (#allergic_to test_cases));
|
|
127
|
-
val passedTests = List.filter (fn x => x) testResults;
|
|
128
|
-
val failedTests = List.filter (fn x => not x) testResults;
|
|
129
|
-
|
|
130
|
-
if (List.length testResults) = (List.length passedTests)
|
|
131
|
-
then (print "ALL TESTS PASSED")
|
|
132
|
-
else (print (Int.toString (List.length failedTests) ^ " TEST(S) FAILED"));
|
|
67
|
+
|
|
68
|
+
val _ = Test.run testsuite
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
structure Expect =
|
|
2
|
+
struct
|
|
3
|
+
datatype expectation = Pass | Fail of string * string
|
|
4
|
+
|
|
5
|
+
local
|
|
6
|
+
fun failEq b a =
|
|
7
|
+
Fail ("Expected: " ^ b, "Got: " ^ a)
|
|
8
|
+
|
|
9
|
+
fun failExn b a =
|
|
10
|
+
Fail ("Expected: " ^ b, "Raised: " ^ a)
|
|
11
|
+
|
|
12
|
+
fun exnName (e: exn): string = General.exnName e
|
|
13
|
+
in
|
|
14
|
+
fun truthy a =
|
|
15
|
+
if a
|
|
16
|
+
then Pass
|
|
17
|
+
else failEq "true" "false"
|
|
18
|
+
|
|
19
|
+
fun falsy a =
|
|
20
|
+
if a
|
|
21
|
+
then failEq "false" "true"
|
|
22
|
+
else Pass
|
|
23
|
+
|
|
24
|
+
fun equalTo b a =
|
|
25
|
+
if a = b
|
|
26
|
+
then Pass
|
|
27
|
+
else failEq (PolyML.makestring b) (PolyML.makestring a)
|
|
28
|
+
|
|
29
|
+
fun nearTo b a =
|
|
30
|
+
if Real.== (a, b)
|
|
31
|
+
then Pass
|
|
32
|
+
else failEq (Real.toString b) (Real.toString a)
|
|
33
|
+
|
|
34
|
+
fun anyError f =
|
|
35
|
+
(
|
|
36
|
+
f ();
|
|
37
|
+
failExn "an exception" "Nothing"
|
|
38
|
+
) handle _ => Pass
|
|
39
|
+
|
|
40
|
+
fun error e f =
|
|
41
|
+
(
|
|
42
|
+
f ();
|
|
43
|
+
failExn (exnName e) "Nothing"
|
|
44
|
+
) handle e' => if exnMessage e' = exnMessage e
|
|
45
|
+
then Pass
|
|
46
|
+
else failExn (exnMessage e) (exnMessage e')
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
structure TermColor =
|
|
51
|
+
struct
|
|
52
|
+
datatype color = Red | Green | Yellow | Normal
|
|
53
|
+
|
|
54
|
+
fun f Red = "\027[31m"
|
|
55
|
+
| f Green = "\027[32m"
|
|
56
|
+
| f Yellow = "\027[33m"
|
|
57
|
+
| f Normal = "\027[0m"
|
|
58
|
+
|
|
59
|
+
fun colorize color s = (f color) ^ s ^ (f Normal)
|
|
60
|
+
|
|
61
|
+
val redit = colorize Red
|
|
62
|
+
|
|
63
|
+
val greenit = colorize Green
|
|
64
|
+
|
|
65
|
+
val yellowit = colorize Yellow
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
structure Test =
|
|
69
|
+
struct
|
|
70
|
+
datatype testnode = TestGroup of string * testnode list
|
|
71
|
+
| Test of string * (unit -> Expect.expectation)
|
|
72
|
+
|
|
73
|
+
local
|
|
74
|
+
datatype evaluation = Success of string
|
|
75
|
+
| Failure of string * string * string
|
|
76
|
+
| Error of string * string
|
|
77
|
+
|
|
78
|
+
fun indent n s = (implode (List.tabulate (n, fn _ => #" "))) ^ s
|
|
79
|
+
|
|
80
|
+
fun fmt indentlvl ev =
|
|
81
|
+
let
|
|
82
|
+
val check = TermColor.greenit "\226\156\148 " (* ✔ *)
|
|
83
|
+
val cross = TermColor.redit "\226\156\150 " (* ✖ *)
|
|
84
|
+
val indentlvl = indentlvl * 2
|
|
85
|
+
in
|
|
86
|
+
case ev of
|
|
87
|
+
Success descr => indent indentlvl (check ^ descr)
|
|
88
|
+
| Failure (descr, exp, got) =>
|
|
89
|
+
String.concatWith "\n" [indent indentlvl (cross ^ descr),
|
|
90
|
+
indent (indentlvl + 2) exp,
|
|
91
|
+
indent (indentlvl + 2) got]
|
|
92
|
+
| Error (descr, reason) =>
|
|
93
|
+
String.concatWith "\n" [indent indentlvl (cross ^ descr),
|
|
94
|
+
indent (indentlvl + 2) (TermColor.redit reason)]
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
fun eval (TestGroup _) = raise Fail "Only a 'Test' can be evaluated"
|
|
98
|
+
| eval (Test (descr, thunk)) =
|
|
99
|
+
(
|
|
100
|
+
case thunk () of
|
|
101
|
+
Expect.Pass => ((1, 0, 0), Success descr)
|
|
102
|
+
| Expect.Fail (s, s') => ((0, 1, 0), Failure (descr, s, s'))
|
|
103
|
+
)
|
|
104
|
+
handle e => ((0, 0, 1), Error (descr, "Unexpected error: " ^ exnMessage e))
|
|
105
|
+
|
|
106
|
+
fun flatten depth testnode =
|
|
107
|
+
let
|
|
108
|
+
fun sum (x, y, z) (a, b, c) = (x + a, y + b, z + c)
|
|
109
|
+
|
|
110
|
+
fun aux (t, (counter, acc)) =
|
|
111
|
+
let
|
|
112
|
+
val (counter', texts) = flatten (depth + 1) t
|
|
113
|
+
in
|
|
114
|
+
(sum counter' counter, texts :: acc)
|
|
115
|
+
end
|
|
116
|
+
in
|
|
117
|
+
case testnode of
|
|
118
|
+
TestGroup (descr, ts) =>
|
|
119
|
+
let
|
|
120
|
+
val (counter, texts) = foldr aux ((0, 0, 0), []) ts
|
|
121
|
+
in
|
|
122
|
+
(counter, (indent (depth * 2) descr) :: List.concat texts)
|
|
123
|
+
end
|
|
124
|
+
| Test _ =>
|
|
125
|
+
let
|
|
126
|
+
val (counter, evaluation) = eval testnode
|
|
127
|
+
in
|
|
128
|
+
(counter, [fmt depth evaluation])
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
fun println s = print (s ^ "\n")
|
|
133
|
+
in
|
|
134
|
+
fun run suite =
|
|
135
|
+
let
|
|
136
|
+
val ((succeeded, failed, errored), texts) = flatten 0 suite
|
|
137
|
+
|
|
138
|
+
val summary = String.concatWith ", " [
|
|
139
|
+
TermColor.greenit ((Int.toString succeeded) ^ " passed"),
|
|
140
|
+
TermColor.redit ((Int.toString failed) ^ " failed"),
|
|
141
|
+
TermColor.redit ((Int.toString errored) ^ " errored"),
|
|
142
|
+
(Int.toString (succeeded + failed + errored)) ^ " total"
|
|
143
|
+
]
|
|
144
|
+
|
|
145
|
+
val status = if failed = 0 andalso errored = 0
|
|
146
|
+
then OS.Process.success
|
|
147
|
+
else OS.Process.failure
|
|
148
|
+
|
|
149
|
+
in
|
|
150
|
+
List.app println texts;
|
|
151
|
+
println "";
|
|
152
|
+
println ("Tests: " ^ summary);
|
|
153
|
+
OS.Process.exit status
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
fun describe description tests = Test.TestGroup (description, tests)
|
|
159
|
+
fun test description thunk = Test.Test (description, thunk)
|
|
@@ -35,19 +35,35 @@ The Hamming distance is only defined for sequences of equal length. This means
|
|
|
35
35
|
that based on the definition, each language could deal with getting sequences
|
|
36
36
|
of equal length differently.
|
|
37
37
|
|
|
38
|
-
##
|
|
38
|
+
## Loading your exercise implementation in PolyML
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
```
|
|
41
|
+
$ poly --use {exercise}.sml
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Or:
|
|
41
45
|
|
|
42
46
|
```
|
|
43
|
-
$ poly
|
|
47
|
+
$ poly
|
|
48
|
+
> use "{exercise}.sml";
|
|
44
49
|
```
|
|
45
50
|
|
|
46
|
-
|
|
51
|
+
**Note:** You have to replace {exercise}.
|
|
52
|
+
|
|
53
|
+
## Running the tests
|
|
54
|
+
|
|
47
55
|
```
|
|
48
|
-
$ poly --use
|
|
56
|
+
$ poly -q --use test.sml
|
|
49
57
|
```
|
|
50
58
|
|
|
59
|
+
## Feedback, Issues, Pull Requests
|
|
60
|
+
|
|
61
|
+
The [exercism/sml](https://github.com/exercism/sml) repository on
|
|
62
|
+
GitHub is the home for all of the Standard ML exercises.
|
|
63
|
+
|
|
64
|
+
If you have feedback about an exercise, or want to help implementing a new
|
|
65
|
+
one, head over there and create an issue. We'll do our best to help you!
|
|
66
|
+
|
|
51
67
|
## Source
|
|
52
68
|
|
|
53
69
|
The Calculating Point Mutations problem at Rosalind [http://rosalind.info/problems/hamm/](http://rosalind.info/problems/hamm/)
|