trackler 2.2.1.19 → 2.2.1.20

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/lib/trackler/version.rb +1 -1
  3. data/tracks/bash/config.json +11 -0
  4. data/tracks/bash/docs/ABOUT.md +5 -0
  5. data/tracks/bash/exercises/word-count/README.md +24 -0
  6. data/tracks/bash/exercises/word-count/example.awk +12 -0
  7. data/tracks/bash/exercises/word-count/example.sh +21 -0
  8. data/tracks/bash/exercises/word-count/word_count_test.sh +84 -0
  9. data/tracks/coffeescript/config/maintainers.json +5 -11
  10. data/tracks/csharp/.travis.yml +3 -0
  11. data/tracks/delphi/config/maintainers.json +1 -1
  12. data/tracks/ecmascript/config.json +108 -108
  13. data/tracks/elixir/exercises/phone-number/phone_number_test.exs +21 -1
  14. data/tracks/factor/docs/SNIPPET.txt +5 -0
  15. data/tracks/idris/docs/TESTS.md +7 -0
  16. data/tracks/java/config.json +47 -47
  17. data/tracks/javascript/config.json +103 -103
  18. data/tracks/julia/config.json +121 -121
  19. data/tracks/julia/docs/RESOURCES.md +1 -1
  20. data/tracks/julia/docs/SNIPPET.txt +8 -0
  21. data/tracks/objective-c/config.json +2 -3
  22. data/tracks/objective-c/exercises/rna-transcription/RNATranscriptionExample.m +11 -32
  23. data/tracks/ocaml/.travis-ci.sh +1 -1
  24. data/tracks/ocaml/.travis.yml +1 -1
  25. data/tracks/ocaml/README.md +1 -1
  26. data/tracks/ocaml/exercises/change/test.ml +24 -21
  27. data/tracks/ocaml/tools/test-generator/src/codegen.ml +3 -7
  28. data/tracks/ocaml/tools/test-generator/src/controller.ml +4 -5
  29. data/tracks/ocaml/tools/test-generator/src/languages.ml +4 -3
  30. data/tracks/ocaml/tools/test-generator/src/model.ml +1 -2
  31. data/tracks/ocaml/tools/test-generator/src/ocaml_special_cases.ml +19 -18
  32. data/tracks/ocaml/tools/test-generator/src/parser.ml +12 -17
  33. data/tracks/ocaml/tools/test-generator/src/purescript_special_cases.ml +11 -3
  34. data/tracks/ocaml/tools/test-generator/test/codegen_test.ml +2 -3
  35. data/tracks/ocaml/tools/test-generator/test/ocaml_special_cases_test.ml +12 -4
  36. data/tracks/ocaml/tools/test-generator/test/parser_test.ml +10 -10
  37. data/tracks/purescript/exercises/bob/test/Main.purs +5 -5
  38. data/tracks/ruby/bin/generate +1 -1
  39. data/tracks/ruby/docs/24pullrequests.md +1 -1
  40. data/tracks/ruby/exercises/all-your-base/all_your_base_test.rb +24 -24
  41. data/tracks/ruby/exercises/alphametics/.meta/generator/test_template.erb +1 -1
  42. data/tracks/ruby/exercises/bowling/.meta/generator/test_template.erb +1 -1
  43. data/tracks/ruby/exercises/bowling/bowling_test.rb +10 -10
  44. data/tracks/ruby/exercises/change/.meta/.version +1 -1
  45. data/tracks/ruby/exercises/change/.meta/solutions/change.rb +1 -1
  46. data/tracks/ruby/exercises/change/change_test.rb +7 -2
  47. data/tracks/ruby/exercises/collatz-conjecture/.meta/generator/collatz_conjecture_case.rb +1 -1
  48. data/tracks/ruby/exercises/connect/.meta/generator/test_template.erb +1 -1
  49. data/tracks/ruby/exercises/dominoes/.meta/generator/test_template.erb +1 -1
  50. data/tracks/ruby/exercises/hamming/.meta/generator/hamming_case.rb +5 -1
  51. data/tracks/ruby/exercises/hamming/hamming_test.rb +7 -7
  52. data/tracks/ruby/exercises/leap/.meta/generator/test_template.erb +1 -1
  53. data/tracks/ruby/exercises/pangram/.meta/.version +1 -1
  54. data/tracks/ruby/exercises/pangram/.meta/solutions/pangram.rb +1 -1
  55. data/tracks/ruby/exercises/pangram/pangram_test.rb +3 -3
  56. data/tracks/ruby/exercises/rna-transcription/rna_transcription_test.rb +4 -4
  57. data/tracks/ruby/exercises/roman-numerals/.meta/solutions/roman_numerals.rb +1 -1
  58. data/tracks/ruby/exercises/space-age/.meta/generator/test_template.erb +1 -1
  59. data/tracks/ruby/lib/generator/test_template.erb +1 -1
  60. data/tracks/ruby/lib/generator/underscore.rb +1 -1
  61. data/tracks/ruby/lib/helper.rb +4 -4
  62. data/tracks/ruby/test/fixtures/{xruby → ruby}/exercises/alpha-beta/.meta/generator/test_template.erb +1 -1
  63. data/tracks/ruby/test/fixtures/{xruby → ruby}/exercises/alpha/.meta/.version +0 -0
  64. data/tracks/ruby/test/fixtures/{xruby → ruby}/exercises/alpha/.meta/generator/alpha_case.rb +0 -0
  65. data/tracks/ruby/test/fixtures/{xruby → ruby}/exercises/alpha/.meta/generator/test_template.erb +1 -1
  66. data/tracks/ruby/test/fixtures/{xruby → ruby}/exercises/alpha/.meta/solutions/alpha.rb +0 -0
  67. data/tracks/ruby/test/fixtures/{xruby → ruby}/exercises/beta/.meta/.version +0 -0
  68. data/tracks/ruby/test/fixtures/{xruby → ruby}/exercises/beta/.meta/generator/beta_case.rb +0 -0
  69. data/tracks/ruby/test/fixtures/{xruby → ruby}/lib/generator/test_template.erb +1 -1
  70. data/tracks/ruby/test/generator/files/track_files_test.rb +4 -4
  71. data/tracks/ruby/test/generator/implementation_test.rb +1 -1
  72. data/tracks/ruby/test/generator/template_values_test.rb +1 -1
  73. data/tracks/scala/exercises/rail-fence-cipher/src/main/scala/{RailFenceCipher.scala → .keep} +0 -0
  74. data/tracks/scala/exercises/rail-fence-cipher/src/test/scala/RailFenceCipherTest.scala +16 -23
  75. data/tracks/scala/exercises/say/src/test/scala/SayTest.scala +20 -33
  76. data/tracks/scala/testgen/src/main/scala/RailFenceCipherTestGenerator.scala +9 -53
  77. data/tracks/scala/testgen/src/main/scala/SayTestGenerator.scala +50 -0
  78. data/tracks/sml/bin/generate +1 -1
  79. data/tracks/sml/config.json +30 -0
  80. data/tracks/sml/exercises/all-your-base/README.md +61 -0
  81. data/tracks/sml/exercises/all-your-base/all-your-base.sml +2 -0
  82. data/tracks/sml/exercises/all-your-base/example.sml +36 -0
  83. data/tracks/sml/exercises/all-your-base/test.sml +75 -0
  84. data/tracks/sml/exercises/all-your-base/testlib.sml +159 -0
  85. data/tracks/sml/exercises/difference-of-squares/example.sml +3 -6
  86. data/tracks/sml/exercises/list-ops/README.md +40 -0
  87. data/tracks/sml/exercises/list-ops/example.sml +34 -0
  88. data/tracks/sml/exercises/list-ops/list-ops.sml +23 -0
  89. data/tracks/sml/exercises/list-ops/test.sml +85 -0
  90. data/tracks/sml/exercises/list-ops/testlib.sml +159 -0
  91. data/tracks/sml/exercises/prime-factors/README.md +66 -0
  92. data/tracks/sml/exercises/prime-factors/example.sml +15 -0
  93. data/tracks/sml/exercises/prime-factors/prime-factors.sml +2 -0
  94. data/tracks/sml/exercises/prime-factors/test.sml +35 -0
  95. data/tracks/sml/exercises/prime-factors/testlib.sml +159 -0
  96. metadata +34 -11
@@ -0,0 +1,40 @@
1
+ # List Ops
2
+
3
+ Implement basic list operations.
4
+
5
+ In functional languages list operations like `length`, `map`, and
6
+ `reduce` are very common. Implement a series of basic list operations,
7
+ without using existing functions.
8
+
9
+ ## Loading your exercise implementation in PolyML
10
+
11
+ ```
12
+ $ poly --use {exercise}.sml
13
+ ```
14
+
15
+ Or:
16
+
17
+ ```
18
+ $ poly
19
+ > use "{exercise}.sml";
20
+ ```
21
+
22
+ **Note:** You have to replace {exercise}.
23
+
24
+ ## Running the tests
25
+
26
+ ```
27
+ $ poly -q --use test.sml
28
+ ```
29
+
30
+ ## Feedback, Issues, Pull Requests
31
+
32
+ The [exercism/sml](https://github.com/exercism/sml) repository on
33
+ GitHub is the home for all of the Standard ML exercises.
34
+
35
+ If you have feedback about an exercise, or want to help implementing a new
36
+ one, head over there and create an issue. We'll do our best to help you!
37
+
38
+
39
+ ## Submitting Incomplete Solutions
40
+ It's possible to submit an incomplete solution so you can see how others have completed the exercise.
@@ -0,0 +1,34 @@
1
+ fun concat [] = []
2
+ | concat [[]] = []
3
+ | concat ([] :: xss) = concat xss
4
+ | concat ((x :: xs) :: xss) = x :: concat (xs :: xss)
5
+
6
+ fun reverse xs =
7
+ let
8
+ fun reverse' acc [] = acc
9
+ | reverse' acc (x :: xs) = reverse' (x :: acc) xs
10
+ in
11
+ reverse' [] xs
12
+ end
13
+
14
+ fun filter (predicate, []) = []
15
+ | filter (predicate, (x :: xs)) =
16
+ if predicate x
17
+ then x :: filter (predicate, xs)
18
+ else filter (predicate, xs)
19
+
20
+ fun map (f, []) = []
21
+ | map (f, x :: xs) = f x :: map (f, xs)
22
+
23
+ fun append (xs, []) = xs
24
+ | append ([], ys) = ys
25
+ | append (x :: xs, ys) = x :: append(xs, ys)
26
+
27
+ fun length [] = 0
28
+ | length (x :: xs) = 1 + length xs
29
+
30
+ fun foldl (_, acc, []) = acc
31
+ | foldl (f, acc, (x :: xs)) = foldl (f, (f (acc, x)), xs)
32
+
33
+ fun foldr (f, acc, []) = acc
34
+ | foldr (f, acc, (x::xs)) = f (x, (foldr (f, acc, xs)))
@@ -0,0 +1,23 @@
1
+ fun concat (lists: int list list): int list =
2
+ raise Fail "'concat' is not implemented"
3
+
4
+ fun reverse (list: int list): int list =
5
+ raise Fail "'reverse' is not implemented"
6
+
7
+ fun filter (function: int -> bool, list: int list): int list =
8
+ raise Fail "'filter' is not implemented"
9
+
10
+ fun map (function: int -> int, list: int list): int list =
11
+ raise Fail "'map' is not implemented"
12
+
13
+ fun append (list1: int list, list2: int list): int list =
14
+ raise Fail "'append' is not implemented"
15
+
16
+ fun length (ns: int list): int =
17
+ raise Fail "'length' is not implemented"
18
+
19
+ fun foldl (function: int * int -> int, initial: int, list: int list): int =
20
+ raise Fail "'foldl' is not implemented"
21
+
22
+ fun foldr (function: int * int -> int, initial: int, list: int list): int =
23
+ raise Fail "'foldr' is not implemented"
@@ -0,0 +1,85 @@
1
+ (* version 2.0.0 *)
2
+
3
+ use "testlib.sml";
4
+ use "list-ops.sml";
5
+
6
+ infixr |>
7
+ fun x |> f = f x
8
+
9
+ val testsuite =
10
+ describe "list-ops" [
11
+ describe "append entries to a list and return the new list" [
12
+ test "empty lists"
13
+ (fn _ => append ([], []) |> Expect.equalTo []),
14
+
15
+ test "empty list to list"
16
+ (fn _ => append ([], [1, 2, 3, 4]) |> Expect.equalTo [1, 2, 3, 4]),
17
+
18
+ test "non-empty lists"
19
+ (fn _ => append ([1, 2], [2, 3, 4, 5]) |> Expect.equalTo [1, 2, 2, 3, 4, 5])
20
+ ],
21
+
22
+ describe "concat lists and lists of list into a new list" [
23
+ test "empty list"
24
+ (fn _ => concat ([]) |> Expect.equalTo []),
25
+
26
+ test "list of lists"
27
+ (fn _ => concat ([[1, 2], [3], [], [4, 5, 6]]) |> Expect.equalTo [1, 2, 3, 4, 5, 6])
28
+ ],
29
+
30
+ describe "filter list returning only values that satisfy the filter function" [
31
+ test "empty list"
32
+ (fn _ => filter (fn n => n mod 2 = 1, []) |> Expect.equalTo []),
33
+
34
+ test "non-empty list"
35
+ (fn _ => filter (fn n => n mod 2 = 1, [1, 2, 3, 5]) |> Expect.equalTo [1, 3, 5])
36
+ ],
37
+
38
+ describe "returns the length of a list" [
39
+ test "empty list"
40
+ (fn _ => length ([]) |> Expect.equalTo 0),
41
+
42
+ test "non-empty list"
43
+ (fn _ => length ([1, 2, 3, 4]) |> Expect.equalTo 4)
44
+ ],
45
+
46
+ describe "return a list of elements whos values equal the list value transformed by the mapping function" [
47
+ test "empty list"
48
+ (fn _ => map (fn n => n + 1, []) |> Expect.equalTo []),
49
+
50
+ test "non-empty list"
51
+ (fn _ => map (fn n => n + 1, [1, 3, 5, 7]) |> Expect.equalTo [2, 4, 6, 8])
52
+ ],
53
+
54
+ describe "folds (reduces) the given list from the left with a function" [
55
+ test "empty list"
56
+ (fn _ => foldl (fn (x, y) => x * y, 2, []) |> Expect.equalTo 2),
57
+
58
+ test "direction independent function applied to non-empty list"
59
+ (fn _ => foldl (fn (x, y) => x + y, 5, [1, 2, 3, 4]) |> Expect.equalTo 15),
60
+
61
+ test "direction dependent function applied to non-empty list"
62
+ (fn _ => foldl (fn (x, y) => x div y, 5, [2, 5]) |> Expect.equalTo 0)
63
+ ],
64
+
65
+ describe "folds (reduces) the given list from the right with a function" [
66
+ test "empty list"
67
+ (fn _ => foldr (fn (x, y) => x * y, 2, []) |> Expect.equalTo 2),
68
+
69
+ test "direction independent function applied to non-empty list"
70
+ (fn _ => foldr (fn (x, y) => x + y, 5, [1, 2, 3, 4]) |> Expect.equalTo 15),
71
+
72
+ test "direction dependent function applied to non-empty list"
73
+ (fn _ => foldr (fn (x, y) => x div y, 5, [2, 5]) |> Expect.equalTo 2)
74
+ ],
75
+
76
+ describe "reverse the elements of the list" [
77
+ test "empty list"
78
+ (fn _ => reverse ([]) |> Expect.equalTo []),
79
+
80
+ test "non-empty list"
81
+ (fn _ => reverse ([1, 3, 5, 7]) |> Expect.equalTo [7, 5, 3, 1])
82
+ ]
83
+ ]
84
+
85
+ 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)
@@ -0,0 +1,66 @@
1
+ # Prime Factors
2
+
3
+ Compute the prime factors of a given natural number.
4
+
5
+ A prime number is only evenly divisible by itself and 1.
6
+
7
+ Note that 1 is not a prime number.
8
+
9
+ ## Example
10
+
11
+ What are the prime factors of 60?
12
+
13
+ - Our first divisor is 2. 2 goes into 60, leaving 30.
14
+ - 2 goes into 30, leaving 15.
15
+ - 2 doesn't go cleanly into 15. So let's move on to our next divisor, 3.
16
+ - 3 goes cleanly into 15, leaving 5.
17
+ - 3 does not go cleanly into 5. The next possible factor is 4.
18
+ - 4 does not go cleanly into 5. The next possible factor is 5.
19
+ - 5 does go cleanly into 5.
20
+ - We're left only with 1, so now, we're done.
21
+
22
+ Our successful divisors in that computation represent the list of prime
23
+ factors of 60: 2, 2, 3, and 5.
24
+
25
+ You can check this yourself:
26
+
27
+ - 2 * 2 * 3 * 5
28
+ - = 4 * 15
29
+ - = 60
30
+ - Success!
31
+
32
+ ## Loading your exercise implementation in PolyML
33
+
34
+ ```
35
+ $ poly --use {exercise}.sml
36
+ ```
37
+
38
+ Or:
39
+
40
+ ```
41
+ $ poly
42
+ > use "{exercise}.sml";
43
+ ```
44
+
45
+ **Note:** You have to replace {exercise}.
46
+
47
+ ## Running the tests
48
+
49
+ ```
50
+ $ poly -q --use test.sml
51
+ ```
52
+
53
+ ## Feedback, Issues, Pull Requests
54
+
55
+ The [exercism/sml](https://github.com/exercism/sml) repository on
56
+ GitHub is the home for all of the Standard ML exercises.
57
+
58
+ If you have feedback about an exercise, or want to help implementing a new
59
+ one, head over there and create an issue. We'll do our best to help you!
60
+
61
+ ## Source
62
+
63
+ The Prime Factors Kata by Uncle Bob [http://butunclebob.com/ArticleS.UncleBob.ThePrimeFactorsKata](http://butunclebob.com/ArticleS.UncleBob.ThePrimeFactorsKata)
64
+
65
+ ## Submitting Incomplete Solutions
66
+ It's possible to submit an incomplete solution so you can see how others have completed the exercise.
@@ -0,0 +1,15 @@
1
+ fun factors n =
2
+ let
3
+ fun aux prime n =
4
+ if prime * prime > n
5
+ then [n]
6
+ else if n mod prime = 0
7
+ then prime :: aux prime (n div prime)
8
+ else if prime = 2
9
+ then aux (prime + 1) n
10
+ else aux (prime + 2) n
11
+ in
12
+ if n < 2
13
+ then []
14
+ else aux 2 n
15
+ end
@@ -0,0 +1,2 @@
1
+ fun factors (input: int): int list =
2
+ raise Fail "'factors' is not implemented"
@@ -0,0 +1,35 @@
1
+ (* version 1.0.0 *)
2
+
3
+ use "prime-factors.sml";
4
+ use "testlib.sml";
5
+
6
+ infixr |>
7
+ fun x |> f = f x
8
+
9
+ val testsuite =
10
+ describe "prime-factors" [
11
+ describe "returns prime factors for the given input number" [
12
+ test "no factors"
13
+ (fn _ => factors (1) |> Expect.equalTo []),
14
+
15
+ test "prime number"
16
+ (fn _ => factors (2) |> Expect.equalTo [2]),
17
+
18
+ test "square of a prime"
19
+ (fn _ => factors (9) |> Expect.equalTo [3, 3]),
20
+
21
+ test "cube of a prime"
22
+ (fn _ => factors (8) |> Expect.equalTo [2, 2, 2]),
23
+
24
+ test "product of primes and non-primes"
25
+ (fn _ => factors (12) |> Expect.equalTo [2, 2, 3]),
26
+
27
+ test "product of primes"
28
+ (fn _ => factors (901255) |> Expect.equalTo [5, 17, 23, 461]),
29
+
30
+ test "factors include a large prime"
31
+ (fn _ => factors (93819012551) |> Expect.equalTo [11, 9539, 894119])
32
+ ]
33
+ ]
34
+
35
+ val _ = Test.run testsuite