trackler 2.2.1.16 → 2.2.1.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/lib/trackler/version.rb +1 -1
  3. data/tracks/delphi/config/maintainers.json +1 -1
  4. data/tracks/objective-c/docs/SNIPPET.txt +10 -0
  5. data/tracks/python/.gitignore +1 -0
  6. data/tracks/python/exercises/accumulate/accumulate.py +1 -1
  7. data/tracks/python/exercises/allergies/allergies.py +9 -1
  8. data/tracks/python/exercises/alphametics/alphametics.py +1 -1
  9. data/tracks/python/exercises/anagram/anagram.py +1 -1
  10. data/tracks/python/exercises/atbash-cipher/atbash_cipher.py +2 -2
  11. data/tracks/python/exercises/beer-song/beer_song.py +2 -2
  12. data/tracks/python/exercises/binary/binary.py +1 -1
  13. data/tracks/python/exercises/binary-search/binary_search.py +1 -1
  14. data/tracks/python/exercises/bob/bob.py +1 -1
  15. data/tracks/python/exercises/book-store/book_store.py +1 -1
  16. data/tracks/python/exercises/bracket-push/bracket_push.py +1 -1
  17. data/tracks/python/requirements-travis.txt +1 -1
  18. data/tracks/rust/config.json +21 -7
  19. data/tracks/rust/exercises/crypto-square/.gitignore +7 -0
  20. data/tracks/rust/exercises/crypto-square/Cargo-example.toml +7 -0
  21. data/tracks/rust/exercises/crypto-square/Cargo.toml +6 -0
  22. data/tracks/rust/exercises/crypto-square/README.md +106 -0
  23. data/tracks/rust/exercises/crypto-square/example.rs +114 -0
  24. data/tracks/rust/exercises/crypto-square/src/lib.rs +3 -0
  25. data/tracks/rust/exercises/crypto-square/tests/crypto-square.rs +81 -0
  26. data/tracks/sml/Makefile +1 -1
  27. data/tracks/sml/config.json +30 -0
  28. data/tracks/sml/exercises/atbash-cipher/README.md +64 -0
  29. data/tracks/sml/exercises/atbash-cipher/atbash-cipher.sml +5 -0
  30. data/tracks/sml/exercises/atbash-cipher/example.sml +32 -0
  31. data/tracks/sml/exercises/atbash-cipher/test.sml +52 -0
  32. data/tracks/sml/exercises/atbash-cipher/testlib.sml +159 -0
  33. data/tracks/sml/exercises/pangram/README.md +45 -0
  34. data/tracks/sml/exercises/pangram/example.sml +18 -0
  35. data/tracks/sml/exercises/pangram/pangram.sml +2 -0
  36. data/tracks/sml/exercises/pangram/test.sml +41 -0
  37. data/tracks/sml/exercises/pangram/testlib.sml +159 -0
  38. data/tracks/sml/exercises/perfect-numbers/README.md +54 -0
  39. data/tracks/sml/exercises/perfect-numbers/example.sml +26 -0
  40. data/tracks/sml/exercises/perfect-numbers/perfect-numbers.sml +6 -0
  41. data/tracks/sml/exercises/perfect-numbers/test.sml +59 -0
  42. data/tracks/sml/exercises/perfect-numbers/testlib.sml +159 -0
  43. metadata +24 -1
@@ -0,0 +1,32 @@
1
+ fun chunkify chunkSz s =
2
+ let
3
+ val sz = size s
4
+
5
+ fun chunker 0 _ = chunker chunkSz (substring (s, 0, chunkSz))
6
+ | chunker i acc =
7
+ if sz = i
8
+ then acc
9
+ else if sz - i < chunkSz
10
+ then acc ^ " " ^ substring (s, i, size s - i)
11
+ else chunker (i + chunkSz) (acc ^ " " ^ substring (s, i, chunkSz))
12
+ in
13
+ if chunkSz > sz
14
+ then s
15
+ else chunker 0 ""
16
+ end
17
+
18
+ fun cipher c =
19
+ let
20
+ open Char
21
+ val n = ord #"z" + ord #"a"
22
+ val c = toLower c
23
+ in
24
+ if isAlpha c
25
+ then (toString o chr) (n - ord c)
26
+ else if isDigit c
27
+ then toString c
28
+ else ""
29
+ end
30
+
31
+ val decode = String.translate cipher
32
+ val encode = (chunkify 5) o decode
@@ -0,0 +1,52 @@
1
+ (* version 1.0.0 *)
2
+
3
+ use "atbash-cipher.sml";
4
+ use "testlib.sml";
5
+
6
+ infixr |>
7
+ fun x |> f = f x
8
+
9
+ val testsuite =
10
+ describe "atbash-cipher" [
11
+ describe "encode" [
12
+ test "encode yes"
13
+ (fn _ => encode ("yes") |> Expect.equalTo "bvh"),
14
+
15
+ test "encode no"
16
+ (fn _ => encode ("no") |> Expect.equalTo "ml"),
17
+
18
+ test "encode OMG"
19
+ (fn _ => encode ("OMG") |> Expect.equalTo "lnt"),
20
+
21
+ test "encode spaces"
22
+ (fn _ => encode ("O M G") |> Expect.equalTo "lnt"),
23
+
24
+ test "encode mindblowingly"
25
+ (fn _ => encode ("mindblowingly") |> Expect.equalTo "nrmwy oldrm tob"),
26
+
27
+ test "encode numbers"
28
+ (fn _ => encode ("Testing,1 2 3, testing.") |> Expect.equalTo "gvhgr mt123 gvhgr mt"),
29
+
30
+ test "encode deep thought"
31
+ (fn _ => encode ("Truth is fiction.") |> Expect.equalTo "gifgs rhurx grlm"),
32
+
33
+ test "encode all the letters"
34
+ (fn _ => encode ("The quick brown fox jumps over the lazy dog.") |> Expect.equalTo "gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt")
35
+ ],
36
+
37
+ describe "decode" [
38
+ test "decode exercism"
39
+ (fn _ => decode ("vcvix rhn") |> Expect.equalTo "exercism"),
40
+
41
+ test "decode a sentence"
42
+ (fn _ => decode ("zmlyh gzxov rhlug vmzhg vkkrm thglm v") |> Expect.equalTo "anobstacleisoftenasteppingstone"),
43
+
44
+ test "decode numbers"
45
+ (fn _ => decode ("gvhgr mt123 gvhgr mt") |> Expect.equalTo "testing123testing"),
46
+
47
+ test "decode all the letters"
48
+ (fn _ => decode ("gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt") |> Expect.equalTo "thequickbrownfoxjumpsoverthelazydog")
49
+ ]
50
+ ]
51
+
52
+ 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,45 @@
1
+ # Pangram
2
+
3
+ Determine if a sentence is a pangram. A pangram (Greek: παν γράμμα, pan gramma,
4
+ "every letter") is a sentence using every letter of the alphabet at least once.
5
+ The best known English pangram is:
6
+ > The quick brown fox jumps over the lazy dog.
7
+
8
+ The alphabet used consists of ASCII letters `a` to `z`, inclusive, and is case
9
+ insensitive. Input will not contain non-ASCII symbols.
10
+
11
+ ## Loading your exercise implementation in PolyML
12
+
13
+ ```
14
+ $ poly --use {exercise}.sml
15
+ ```
16
+
17
+ Or:
18
+
19
+ ```
20
+ $ poly
21
+ > use "{exercise}.sml";
22
+ ```
23
+
24
+ **Note:** You have to replace {exercise}.
25
+
26
+ ## Running the tests
27
+
28
+ ```
29
+ $ poly -q --use test.sml
30
+ ```
31
+
32
+ ## Feedback, Issues, Pull Requests
33
+
34
+ The [exercism/sml](https://github.com/exercism/sml) repository on
35
+ GitHub is the home for all of the Standard ML exercises.
36
+
37
+ If you have feedback about an exercise, or want to help implementing a new
38
+ one, head over there and create an issue. We'll do our best to help you!
39
+
40
+ ## Source
41
+
42
+ Wikipedia [https://en.wikipedia.org/wiki/Pangram](https://en.wikipedia.org/wiki/Pangram)
43
+
44
+ ## Submitting Incomplete Solutions
45
+ It's possible to submit an incomplete solution so you can see how others have completed the exercise.
@@ -0,0 +1,18 @@
1
+ fun isPangram (input: string): bool =
2
+ let
3
+ val counter = Array.tabulate (26, fn _ => 0)
4
+ val chars = map Char.toLower (String.explode input)
5
+ val aCode = ord #"a"
6
+
7
+ fun updateCounter c =
8
+ let
9
+ val index = ord c - aCode
10
+ in
11
+ if index < 0
12
+ then ()
13
+ else Array.update (counter, index, (Array.sub (counter, index)) + 1)
14
+ end
15
+ in
16
+ List.app updateCounter chars;
17
+ Array.all (fn x => x > 0) counter
18
+ end
@@ -0,0 +1,2 @@
1
+ fun isPangram (input: string): bool =
2
+ raise Fail "'isPangram' is not implemented"
@@ -0,0 +1,41 @@
1
+ (* version 1.1.0 *)
2
+
3
+ use "pangram.sml";
4
+ use "testlib.sml";
5
+
6
+ infixr |>
7
+ fun x |> f = f x
8
+
9
+ val testsuite =
10
+ describe "pangram" [
11
+ describe "Check if the given string is an pangram" [
12
+ test "sentence empty"
13
+ (fn _ => isPangram ("") |> Expect.falsy),
14
+
15
+ test "pangram with only lower case"
16
+ (fn _ => isPangram ("the quick brown fox jumps over the lazy dog") |> Expect.truthy),
17
+
18
+ test "missing character 'x'"
19
+ (fn _ => isPangram ("a quick movement of the enemy will jeopardize five gunboats") |> Expect.falsy),
20
+
21
+ test "another missing character 'x'"
22
+ (fn _ => isPangram ("the quick brown fish jumps over the lazy dog") |> Expect.falsy),
23
+
24
+ test "pangram with underscores"
25
+ (fn _ => isPangram ("the_quick_brown_fox_jumps_over_the_lazy_dog") |> Expect.truthy),
26
+
27
+ test "pangram with numbers"
28
+ (fn _ => isPangram ("the 1 quick brown fox jumps over the 2 lazy dogs") |> Expect.truthy),
29
+
30
+ test "missing letters replaced by numbers"
31
+ (fn _ => isPangram ("7h3 qu1ck brown fox jumps ov3r 7h3 lazy dog") |> Expect.falsy),
32
+
33
+ test "pangram with mixed case and punctuation"
34
+ (fn _ => isPangram ("\"Five quacking Zephyrs jolt my wax bed.\"") |> Expect.truthy),
35
+
36
+ test "upper and lower case versions of the same character should not be counted separately"
37
+ (fn _ => isPangram ("the quick brown fox jumps over with lazy FX") |> Expect.falsy)
38
+ ]
39
+ ]
40
+
41
+ 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,54 @@
1
+ # Perfect Numbers
2
+
3
+ Determine if a number is perfect, abundant, or deficient based on
4
+ Nicomachus' (60 - 120 CE) classification scheme for natural numbers.
5
+
6
+ The Greek mathematician [Nicomachus](https://en.wikipedia.org/wiki/Nicomachus) devised a classification scheme for natural numbers, identifying each as belonging uniquely to the categories of **perfect**, **abundant**, or **deficient** based on their [aliquot sum](https://en.wikipedia.org/wiki/Aliquot_sum). The aliquot sum is defined as the sum of the factors of a number not including the number itself. For example, the aliquot sum of 15 is (1 + 3 + 5) = 9
7
+
8
+ - **Perfect**: aliquot sum = number
9
+ - 6 is a perfect number because (1 + 2 + 3) = 6
10
+ - 28 is a perfect number because (1 + 2 + 4 + 7 + 14) = 28
11
+ - **Abundant**: aliquot sum > number
12
+ - 12 is an abundant number because (1 + 2 + 3 + 4 + 6) = 16
13
+ - 24 is an abundant number because (1 + 2 + 3 + 4 + 6 + 8 + 12) = 36
14
+ - **Deficient**: aliquot sum < number
15
+ - 8 is a deficient number because (1 + 2 + 4) = 7
16
+ - Prime numbers are deficient
17
+
18
+ Implement the `classify` function, it should return one of `Abundant`, `Deficient` or `Perfect`. If the input param is not a positive integer, raise the exception `NotAPositiveInteger`.
19
+
20
+ ## Loading your exercise implementation in PolyML
21
+
22
+ ```
23
+ $ poly --use {exercise}.sml
24
+ ```
25
+
26
+ Or:
27
+
28
+ ```
29
+ $ poly
30
+ > use "{exercise}.sml";
31
+ ```
32
+
33
+ **Note:** You have to replace {exercise}.
34
+
35
+ ## Running the tests
36
+
37
+ ```
38
+ $ poly -q --use test.sml
39
+ ```
40
+
41
+ ## Feedback, Issues, Pull Requests
42
+
43
+ The [exercism/sml](https://github.com/exercism/sml) repository on
44
+ GitHub is the home for all of the Standard ML exercises.
45
+
46
+ If you have feedback about an exercise, or want to help implementing a new
47
+ one, head over there and create an issue. We'll do our best to help you!
48
+
49
+ ## Source
50
+
51
+ Taken from Chapter 2 of Functional Thinking by Neal Ford. [http://shop.oreilly.com/product/0636920029687.do](http://shop.oreilly.com/product/0636920029687.do)
52
+
53
+ ## Submitting Incomplete Solutions
54
+ It's possible to submit an incomplete solution so you can see how others have completed the exercise.
@@ -0,0 +1,26 @@
1
+ exception NotAPositiveInteger
2
+
3
+ datatype classification = Abundant | Deficient | Perfect
4
+
5
+ fun sigma n =
6
+ let
7
+ fun loop i =
8
+ if i * i > n
9
+ then 0
10
+ else if n mod i <> 0
11
+ then loop (i + 1)
12
+ else if n div i = i
13
+ then i + loop (i + 1)
14
+ else i + (n div i) + loop (i + 1)
15
+ in
16
+ loop 1
17
+ end
18
+
19
+ fun classify n =
20
+ if n < 1
21
+ then raise NotAPositiveInteger
22
+ else
23
+ case Int.compare (sigma n, 2 * n) of
24
+ GREATER => Abundant
25
+ | LESS => Deficient
26
+ | _ => Perfect
@@ -0,0 +1,6 @@
1
+ exception NotAPositiveInteger
2
+
3
+ datatype classification = Abundant | Deficient | Perfect
4
+
5
+ fun classify (input: int): classification =
6
+ raise Fail "'classify' is not implemented"
@@ -0,0 +1,59 @@
1
+ (* version 1.0.1 *)
2
+
3
+ use "perfect-numbers.sml";
4
+ use "testlib.sml";
5
+
6
+ infixr |>
7
+ fun x |> f = f x
8
+
9
+ val testsuite =
10
+ describe "perfect-numbers" [
11
+ describe "Perfect numbers" [
12
+ test "Smallest perfect number is classified correctly"
13
+ (fn _ => classify (6) |> Expect.equalTo Perfect),
14
+
15
+ test "Medium perfect number is classified correctly"
16
+ (fn _ => classify (28) |> Expect.equalTo Perfect),
17
+
18
+ test "Large perfect number is classified correctly"
19
+ (fn _ => classify (33550336) |> Expect.equalTo Perfect)
20
+ ],
21
+
22
+ describe "Abundant numbers" [
23
+ test "Smallest abundant number is classified correctly"
24
+ (fn _ => classify (12) |> Expect.equalTo Abundant),
25
+
26
+ test "Medium abundant number is classified correctly"
27
+ (fn _ => classify (30) |> Expect.equalTo Abundant),
28
+
29
+ test "Large abundant number is classified correctly"
30
+ (fn _ => classify (33550335) |> Expect.equalTo Abundant)
31
+ ],
32
+
33
+ describe "Deficient numbers" [
34
+ test "Smallest prime deficient number is classified correctly"
35
+ (fn _ => classify (2) |> Expect.equalTo Deficient),
36
+
37
+ test "Smallest non-prime deficient number is classified correctly"
38
+ (fn _ => classify (4) |> Expect.equalTo Deficient),
39
+
40
+ test "Medium deficient number is classified correctly"
41
+ (fn _ => classify (32) |> Expect.equalTo Deficient),
42
+
43
+ test "Large deficient number is classified correctly"
44
+ (fn _ => classify (33550337) |> Expect.equalTo Deficient),
45
+
46
+ test "Edge case (no factors other than itself) is classified correctly"
47
+ (fn _ => classify (1) |> Expect.equalTo Deficient)
48
+ ],
49
+
50
+ describe "Invalid inputs" [
51
+ test "Zero is rejected (not a natural number)"
52
+ (fn _ => (fn _ => classify (~1)) |> Expect.error NotAPositiveInteger),
53
+
54
+ test "Negative integer is rejected (not a natural number)"
55
+ (fn _ => (fn _ => classify (~1)) |> Expect.error NotAPositiveInteger)
56
+ ]
57
+ ]
58
+
59
+ val _ = Test.run testsuite