trackler 2.2.1.19 → 2.2.1.20

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.
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,50 @@
1
+ import java.io.File
2
+
3
+ import PrimeFactorsTestGenerator.toString
4
+ import testgen.TestSuiteBuilder.{sutArgs, _}
5
+ import testgen._
6
+
7
+ object SayTestGenerator {
8
+ def main(args: Array[String]): Unit = {
9
+ val file = new File("src/main/resources/say.json")
10
+
11
+ def toString(expected: CanonicalDataParser.Expected): String = {
12
+ expected match {
13
+ case Left(_) => "None"
14
+ case Right(-1) => "None"
15
+ case Right(n) => s"""Some("$n")"""
16
+ }
17
+ }
18
+
19
+ def sutArgs(parseResult: CanonicalDataParser.ParseResult, argNames: String*): String =
20
+ argNames map (name => toArgString(parseResult(name))) mkString ", "
21
+
22
+ def toArgString(any: Any): String = {
23
+ any match {
24
+ case lstr: Long =>
25
+ lstr.toString + "l"
26
+ case istr: Integer =>
27
+ istr.toString
28
+ case dstr: Double =>
29
+ dstr.toLong + "l"
30
+ case _ => any.toString
31
+ }
32
+ }
33
+
34
+ def fromLabeledTest(argNames: String*): ToTestCaseData =
35
+ withLabeledTest { sut =>
36
+ labeledTest =>
37
+ val args = sutArgs(labeledTest.result, argNames: _*)
38
+ val property = labeledTest.property
39
+ val sutCall =
40
+ s"""$sut.inEnglish($args)"""
41
+ val expected = toString(labeledTest.expected)
42
+ TestCaseData(labeledTest.description, sutCall, expected)
43
+ }
44
+
45
+ val code = TestSuiteBuilder.build(file, fromLabeledTest("input"))
46
+ println(s"-------------")
47
+ println(code)
48
+ println(s"-------------")
49
+ }
50
+ }
@@ -212,8 +212,8 @@ def generate_test_content(data, signature):
212
212
  return '\n'.join([
213
213
  '(* version %s *)' % data['version'],
214
214
  '',
215
- 'use "%s.sml";' % data['exercise'],
216
215
  'use "testlib.sml";',
216
+ 'use "%s.sml";' % data['exercise'],
217
217
  '',
218
218
  'infixr |>',
219
219
  'fun x |> f = f x',
@@ -4,6 +4,16 @@
4
4
  "active": false,
5
5
  "test_pattern": "test[.]sml$",
6
6
  "exercises": [
7
+ {
8
+ "uuid": "7e1d0e9a-435d-4dc6-8867-2fc4f9b7fe6f",
9
+ "slug": "all-your-base",
10
+ "core": false,
11
+ "unlocked_by": null,
12
+ "difficulty": 1,
13
+ "topics": [
14
+
15
+ ]
16
+ },
7
17
  {
8
18
  "uuid": "4450455d-0786-6f80-7672-48368a115df16e0aa7e",
9
19
  "slug": "hello-world",
@@ -134,6 +144,26 @@
134
144
 
135
145
  ]
136
146
  },
147
+ {
148
+ "uuid": "6c191163-0a98-2380-debc-75144c1787f3853e868",
149
+ "slug": "prime-factors",
150
+ "core": false,
151
+ "unlocked_by": null,
152
+ "difficulty": 1,
153
+ "topics": [
154
+
155
+ ]
156
+ },
157
+ {
158
+ "uuid": "c8b94fa9-d758-4dca-b7fc-7a130061e064",
159
+ "slug": "list-ops",
160
+ "core": false,
161
+ "unlocked_by": null,
162
+ "difficulty": 1,
163
+ "topics": [
164
+
165
+ ]
166
+ },
137
167
  {
138
168
  "uuid": "225cfd7d-81a3-4a58-b1aa-1de2e40e7a93",
139
169
  "slug": "binary",
@@ -0,0 +1,61 @@
1
+ # All Your Base
2
+
3
+ Convert a number, represented as a sequence of digits in one base, to any other base.
4
+
5
+ Implement general base conversion. Given a number in base a, represented as a sequence of digits, convert it to base b.
6
+
7
+ Note
8
+
9
+ Try to implement the conversion yourself. Do not use something else to perform the conversion for you.
10
+
11
+ About Positional Notation:
12
+
13
+ In positional notation, a number in base b can be understood as a linear combination of powers of b.
14
+
15
+ The number 42, in base 10, means:
16
+
17
+ (4 * 10^1) + (2 * 10^0)
18
+
19
+ The number 101010, in base 2, means:
20
+
21
+ (1 * 2^5) + (0 * 2^4) + (1 * 2^3) + (0 * 2^2) + (1 * 2^1) + (0 * 2^0)
22
+
23
+ The number 1120, in base 3, means:
24
+
25
+ (1 * 3^3) + (1 * 3^2) + (2 * 3^1) + (0 * 3^0)
26
+
27
+ I think you got the idea!
28
+
29
+ Yes. Those three numbers above are exactly the same. Congratulations!
30
+
31
+ ## Loading your exercise implementation in PolyML
32
+
33
+ ```
34
+ $ poly --use {exercise}.sml
35
+ ```
36
+
37
+ Or:
38
+
39
+ ```
40
+ $ poly
41
+ > use "{exercise}.sml";
42
+ ```
43
+
44
+ **Note:** You have to replace {exercise}.
45
+
46
+ ## Running the tests
47
+
48
+ ```
49
+ $ poly -q --use test.sml
50
+ ```
51
+
52
+ ## Feedback, Issues, Pull Requests
53
+
54
+ The [exercism/sml](https://github.com/exercism/sml) repository on
55
+ GitHub is the home for all of the Standard ML exercises.
56
+
57
+ If you have feedback about an exercise, or want to help implementing a new
58
+ one, head over there and create an issue. We'll do our best to help you!
59
+
60
+ ## Submitting Incomplete Solutions
61
+ It's possible to submit an incomplete solution so you can see how others have completed the exercise.
@@ -0,0 +1,2 @@
1
+ fun rebase (input_base: int, input_digits: int list, output_base: int): int list option =
2
+ raise Fail "'rebase' is not implemented"
@@ -0,0 +1,36 @@
1
+ fun rebase (inBase, digits, outBase) = let
2
+ fun fromBase base = let
3
+ fun f (x, NONE ) = NONE
4
+ | f (x, SOME n) =
5
+ if x >= 0 andalso x < base then SOME(n * base + x)
6
+ else NONE
7
+ in
8
+ foldl f (SOME 0)
9
+ end
10
+
11
+ fun toBase base = let
12
+ infix divMod
13
+ fun a divMod b = (a div b, a mod b)
14
+
15
+ fun swap (a, b) = (b, a)
16
+
17
+ fun unfold f b =
18
+ case f b of
19
+ SOME(a, b') => a :: unfold f b'
20
+ | NONE => []
21
+
22
+ fun f 0 = NONE
23
+ | f x = SOME (swap (x divMod base))
24
+ in
25
+ rev o (unfold f)
26
+ end
27
+ in
28
+ if inBase < 2
29
+ orelse outBase < 2
30
+ orelse (List.length digits) = 0
31
+ orelse (List.length digits) = (List.length (List.filter (fn x => x = 0) digits))
32
+ then NONE
33
+ else case fromBase inBase digits of
34
+ SOME v => SOME (toBase outBase v)
35
+ | NONE => NONE
36
+ end
@@ -0,0 +1,75 @@
1
+ (* version 1.1.0 *)
2
+
3
+ use "all-your-base.sml";
4
+ use "testlib.sml";
5
+
6
+ infixr |>
7
+ fun x |> f = f x
8
+
9
+ val testsuite =
10
+ describe "all-your-base" [
11
+ test "single bit one to decimal"
12
+ (fn _ => rebase (2, [1], 10) |> Expect.equalTo (SOME [1])),
13
+
14
+ test "binary to single decimal"
15
+ (fn _ => rebase (2, [1, 0, 1], 10) |> Expect.equalTo (SOME [5])),
16
+
17
+ test "single decimal to binary"
18
+ (fn _ => rebase (10, [5], 2) |> Expect.equalTo (SOME [1, 0, 1])),
19
+
20
+ test "binary to multiple decimal"
21
+ (fn _ => rebase (2, [1, 0, 1, 0, 1, 0], 10) |> Expect.equalTo (SOME [4, 2])),
22
+
23
+ test "decimal to binary"
24
+ (fn _ => rebase (10, [4, 2], 2) |> Expect.equalTo (SOME [1, 0, 1, 0, 1, 0])),
25
+
26
+ test "trinary to hexadecimal"
27
+ (fn _ => rebase (3, [1, 1, 2, 0], 16) |> Expect.equalTo (SOME [2, 10])),
28
+
29
+ test "hexadecimal to trinary"
30
+ (fn _ => rebase (16, [2, 10], 3) |> Expect.equalTo (SOME [1, 1, 2, 0])),
31
+
32
+ test "15-bit integer"
33
+ (fn _ => rebase (97, [3, 46, 60], 73) |> Expect.equalTo (SOME [6, 10, 45])),
34
+
35
+ test "empty list"
36
+ (fn _ => rebase (2, [], 10) |> Expect.equalTo NONE),
37
+
38
+ test "single zero"
39
+ (fn _ => rebase (10, [0], 2) |> Expect.equalTo NONE),
40
+
41
+ test "multiple zeros"
42
+ (fn _ => rebase (10, [0, 0, 0], 2) |> Expect.equalTo NONE),
43
+
44
+ test "leading zeros"
45
+ (fn _ => rebase (7, [0, 6, 0], 10) |> Expect.equalTo (SOME [4, 2])),
46
+
47
+ test "first base is one"
48
+ (fn _ => rebase (1, [], 10) |> Expect.equalTo NONE),
49
+
50
+ test "first base is zero"
51
+ (fn _ => rebase (0, [], 10) |> Expect.equalTo NONE),
52
+
53
+ test "first base is negative"
54
+ (fn _ => rebase (~2, [1], 10) |> Expect.equalTo NONE),
55
+
56
+ test "negative digit"
57
+ (fn _ => rebase (2, [1, ~1, 1, 0, 1, 0], 10) |> Expect.equalTo NONE),
58
+
59
+ test "invalid positive digit"
60
+ (fn _ => rebase (2, [1, 2, 1, 0, 1, 0], 10) |> Expect.equalTo NONE),
61
+
62
+ test "second base is one"
63
+ (fn _ => rebase (2, [1, 0, 1, 0, 1, 0], 1) |> Expect.equalTo NONE),
64
+
65
+ test "second base is zero"
66
+ (fn _ => rebase (10, [7], 0) |> Expect.equalTo NONE),
67
+
68
+ test "second base is negative"
69
+ (fn _ => rebase (2, [1], ~7) |> Expect.equalTo NONE),
70
+
71
+ test "both bases are negative"
72
+ (fn _ => rebase (~2, [1], ~7) |> Expect.equalTo NONE)
73
+ ]
74
+
75
+ 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)
@@ -1,11 +1,8 @@
1
1
  local
2
- val identity = fn x => x
3
- fun range n = List.tabulate (n, identity)
4
2
  fun square n = n * n
5
- val sum = foldl (op +) 0
6
- fun inc n = n + 1
3
+ fun sum n = n * (n + 1) div 2
7
4
  in
8
- val squareOfSum = square o sum o range o inc
9
- fun sumOfSquares n = sum (map square ((range o inc) n))
5
+ val squareOfSum = square o sum
6
+ fun sumOfSquares n = n * (n + 1) * (2 * n + 1) div 6
10
7
  fun differenceOfSquares n = squareOfSum n - sumOfSquares n
11
8
  end