trackler 2.2.1.43 → 2.2.1.44
Sign up to get free protection for your applications and to get access to all the features.
- 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/)
|