trackler 2.2.1.36 → 2.2.1.37

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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/lib/trackler/version.rb +1 -1
  3. data/tracks/bash/config.json +1 -0
  4. data/tracks/ecmascript/README.md +2 -2
  5. data/tracks/haskell/config/maintainers.json +2 -2
  6. data/tracks/java/config.json +15 -3
  7. data/tracks/java/exercises/difference-of-squares/src/test/java/DifferenceOfSquaresCalculatorTest.java +9 -9
  8. data/tracks/ruby/exercises/palindrome-products/README.md +12 -6
  9. data/tracks/ruby/exercises/space-age/.meta/generator/test_template.erb +1 -1
  10. data/tracks/ruby/lib/generator/template_values.rb +6 -0
  11. data/tracks/ruby/lib/generator/test_template.erb +1 -1
  12. data/tracks/ruby/test/generator/template_values_test.rb +3 -3
  13. data/tracks/rust/exercises/accumulate/.gitignore +7 -0
  14. data/tracks/rust/exercises/clock/.gitignore +7 -0
  15. data/tracks/rust/exercises/nth-prime/.gitignore +7 -0
  16. data/tracks/rust/exercises/pig-latin/.gitignore +7 -0
  17. data/tracks/rust/exercises/prime-factors/.gitignore +7 -0
  18. data/tracks/rust/exercises/proverb/.gitignore +7 -0
  19. data/tracks/rust/exercises/pythagorean-triplet/.gitignore +7 -0
  20. data/tracks/rust/exercises/run-length-encoding/.gitignore +7 -0
  21. data/tracks/rust/exercises/say/.gitignore +7 -0
  22. data/tracks/scala/config.json +1 -0
  23. data/tracks/scala/exercises/clock/src/test/scala/ClockTest.scala +73 -79
  24. data/tracks/scala/exercises/forth/src/test/scala/ForthTest.scala +128 -133
  25. data/tracks/scala/exercises/kindergarten-garden/example.scala +1 -1
  26. data/tracks/scala/exercises/kindergarten-garden/src/test/scala/GardenTest.scala +77 -52
  27. data/tracks/scala/exercises/nucleotide-count/src/main/scala/.keep +0 -0
  28. data/tracks/scala/exercises/nucleotide-count/src/test/scala/NucleotideCountTest.scala +21 -61
  29. data/tracks/scala/exercises/palindrome-products/example.scala +7 -4
  30. data/tracks/scala/exercises/palindrome-products/src/test/scala/PalindromeProductsTest.scala +54 -34
  31. data/tracks/scala/testgen/src/main/scala/ClockTestGenerator.scala +66 -0
  32. data/tracks/scala/testgen/src/main/scala/ForthTestGenerator.scala +66 -0
  33. data/tracks/scala/testgen/src/main/scala/KindergartenGardenTestGenerator.scala +48 -0
  34. data/tracks/scala/testgen/src/main/scala/NucleotideCountTestGenerator.scala +34 -0
  35. data/tracks/scala/testgen/src/main/scala/PalindromeProductsTestGenerator.scala +50 -0
  36. data/tracks/scala/testgen/src/main/scala/testgen/CanonicalDataParser.scala +7 -6
  37. data/tracks/sml/config.json +21 -0
  38. data/tracks/sml/exercises/phone-number/README.md +64 -0
  39. data/tracks/sml/exercises/phone-number/example.sml +18 -0
  40. data/tracks/sml/exercises/phone-number/phone-number.sml +2 -0
  41. data/tracks/sml/exercises/phone-number/test.sml +50 -0
  42. data/tracks/sml/exercises/phone-number/testlib.sml +159 -0
  43. data/tracks/sml/exercises/roman-numerals/README.md +79 -0
  44. data/tracks/sml/exercises/roman-numerals/example.sml +27 -0
  45. data/tracks/sml/exercises/roman-numerals/roman-numerals.sml +2 -0
  46. data/tracks/sml/exercises/roman-numerals/test.sml +66 -0
  47. data/tracks/sml/exercises/roman-numerals/testlib.sml +159 -0
  48. metadata +26 -3
  49. data/tracks/scala/exercises/nucleotide-count/src/main/scala/DNA.scala +0 -6
@@ -0,0 +1,50 @@
1
+ import java.io.File
2
+
3
+ import testgen.TestSuiteBuilder.{toString, _}
4
+ import testgen._
5
+
6
+ object PalindromeProductsTestGenerator {
7
+ def main(args: Array[String]): Unit = {
8
+ val file = new File("src/main/resources/palindrome-products.json")
9
+
10
+ def toStringFromMap(m: Map[String, Any]): String =
11
+ s"Some((${m("value").toString}, " +
12
+ s"Set(${m("factors").asInstanceOf[List[List[Int]]].map(xs => "(" + xs.map(_.toString).mkString(", ") + ")").mkString(", ")})))"
13
+
14
+
15
+ def toString(expected: CanonicalDataParser.Expected): String = {
16
+ expected match {
17
+ case Left(_) => "None"
18
+ case Right(m: Map[String, any]) => toStringFromMap(m)
19
+ }
20
+ }
21
+
22
+ def fromLabeledTest(argNames: String*): ToTestCaseData =
23
+ withLabeledTest { sut =>
24
+ labeledTest =>
25
+ val args = sutArgs(labeledTest.result, argNames: _*)
26
+ val property = labeledTest.property
27
+ val sutCall = s"""$sut($args).$property"""
28
+ val expected = toString(labeledTest.expected)
29
+ TestCaseData(labeledTest.description, sutCall, expected)
30
+ }
31
+
32
+ val code =
33
+ TestSuiteBuilder.build(file, fromLabeledTest("input_min", "input_max"),
34
+ Seq(),
35
+ Seq("// PalindromeProducts largest call is expecting a return type of",
36
+ "// Option[(Int, Set[(Int, Int)])] - None is expected for error cases.",
37
+ "// Some is expected for valid cases. The first element of the tuple ",
38
+ "// is the largest palindrome product value. The second element of the",
39
+ "// tuple is the list of factors.",
40
+ "// PalindromeProducts smallest call is expecting a return type of",
41
+ "// Option[(Int, Set[(Int, Int)])] - None is expected for error cases.",
42
+ "// Some is expected for valid cases. The first element of the tuple ",
43
+ "// is the smallest palindrome product value. The second element of the",
44
+ "// tuple is the list of factors."))
45
+
46
+ println(s"-------------")
47
+ println(code)
48
+ println(s"-------------")
49
+ }
50
+ }
@@ -30,7 +30,6 @@ object CanonicalDataParser {
30
30
  val rawParseResult =
31
31
  JSON.parseFull(fileContents).get.asInstanceOf[ParseResult]
32
32
  val parseResult = rawParseResult mapValues restoreInts
33
- println(parseResult)
34
33
  parseResult
35
34
  }
36
35
 
@@ -59,15 +58,17 @@ object Exercise {
59
58
  val cases: Cases =
60
59
  getRequired[Seq[ParseResult]](result, "cases") map LabeledTestItem.fromParseResult
61
60
  Exercise(getRequired(result, "exercise"), getRequired(result, "version"),
62
- flattenCases(cases), getOptional(result, "comments"))
61
+ flattenCases(cases, List()), getOptional(result, "comments"))
63
62
  }
64
63
 
65
64
  // so far there are to few LabeledTestGroups to handle them separately
66
- private def flattenCases(cases: Cases): Cases =
65
+ private def flattenCases(cases: Cases, parentDescriptions: List[String]): Cases =
67
66
  cases match {
68
67
  case Seq() => Seq()
69
- case (ltg: LabeledTestGroup) +: xs => flattenCases(ltg.cases) ++ flattenCases(xs)
70
- case (lt: LabeledTest) +: xs => lt +: flattenCases(xs)
68
+ case (ltg: LabeledTestGroup) +: xs => flattenCases(ltg.cases, ltg.description :: parentDescriptions) ++
69
+ flattenCases(xs, parentDescriptions)
70
+ case (lt: LabeledTest) +: xs => LabeledTest(lt.description, lt.property, lt.expected, lt.result, parentDescriptions) +:
71
+ flattenCases(xs, parentDescriptions)
71
72
  }
72
73
  }
73
74
 
@@ -79,7 +80,7 @@ object LabeledTestItem {
79
80
  }
80
81
 
81
82
  case class LabeledTest(description: Description, property: Property,
82
- expected: Expected, result: ParseResult) extends LabeledTestItem
83
+ expected: Expected, result: ParseResult, parentDescriptions: List[String] = List()) extends LabeledTestItem
83
84
  object LabeledTest {
84
85
  implicit def fromParseResult(result: ParseResult): LabeledTest = {
85
86
  val expected: Expected = {
@@ -214,6 +214,27 @@
214
214
 
215
215
  ]
216
216
  },
217
+ {
218
+ "uuid": "f923bffb-109f-4257-957c-cea8cae2d5c5",
219
+ "slug": "phone-number",
220
+ "core": false,
221
+ "unlocked_by": null,
222
+ "difficulty": 1,
223
+ "topics": [
224
+
225
+ ]
226
+ },
227
+ {
228
+
229
+ "uuid": "b4359037-8457-49ea-ac33-44710ada3b4d",
230
+ "slug": "roman-numerals",
231
+ "core": false,
232
+ "unlocked_by": null,
233
+ "difficulty": 1,
234
+ "topics": [
235
+
236
+ ]
237
+ },
217
238
  {
218
239
  "uuid": "225cfd7d-81a3-4a58-b1aa-1de2e40e7a93",
219
240
  "slug": "binary",
@@ -0,0 +1,64 @@
1
+ # Phone Number
2
+
3
+ Clean up user-entered phone numbers so that they can be sent SMS messages.
4
+
5
+ The **North American Numbering Plan (NANP)** is a telephone numbering system used by many countries in North America like the United States, Canada or Bermuda. All NANP-countries share the same international country code: `1`.
6
+
7
+ NANP numbers are ten-digit numbers consisting of a three-digit Numbering Plan Area code, commonly known as *area code*, followed by a seven-digit local number. The first three digits of the local number represent the *exchange code*, followed by the unique four-digit number which is the *subscriber number*.
8
+
9
+
10
+ The format is usually represented as
11
+ ```
12
+ (NXX)-NXX-XXXX
13
+ ```
14
+ where `N` is any digit from 2 through 9 and `X` is any digit from 0 through 9.
15
+
16
+ Your task is to clean up differently formated telephone numbers by removing punctuation and the country code (1) if present.
17
+
18
+ For example, the inputs
19
+ - `+1 (613)-995-0253`
20
+ - `613-995-0253`
21
+ - `1 613 995 0253`
22
+ - `613.995.0253`
23
+
24
+ should all produce the output
25
+
26
+ `6139950253`
27
+
28
+ **Note:** As this exercise only deals with telephone numbers used in NANP-countries, only 1 is considered a valid country code.
29
+
30
+ ## Loading your exercise implementation in PolyML
31
+
32
+ ```
33
+ $ poly --use {exercise}.sml
34
+ ```
35
+
36
+ Or:
37
+
38
+ ```
39
+ $ poly
40
+ > use "{exercise}.sml";
41
+ ```
42
+
43
+ **Note:** You have to replace {exercise}.
44
+
45
+ ## Running the tests
46
+
47
+ ```
48
+ $ poly -q --use test.sml
49
+ ```
50
+
51
+ ## Feedback, Issues, Pull Requests
52
+
53
+ The [exercism/sml](https://github.com/exercism/sml) repository on
54
+ GitHub is the home for all of the Standard ML exercises.
55
+
56
+ If you have feedback about an exercise, or want to help implementing a new
57
+ one, head over there and create an issue. We'll do our best to help you!
58
+
59
+ ## Source
60
+
61
+ Event Manager by JumpstartLab [http://tutorials.jumpstartlab.com/projects/eventmanager.html](http://tutorials.jumpstartlab.com/projects/eventmanager.html)
62
+
63
+ ## Submitting Incomplete Solutions
64
+ It's possible to submit an incomplete solution so you can see how others have completed the exercise.
@@ -0,0 +1,18 @@
1
+ fun clean text =
2
+ let
3
+ fun valid (#"0" :: _) = false
4
+ | valid (#"1" :: _) = false
5
+ | valid digits = List.nth (digits, 3) > #"1"
6
+
7
+ fun check digits =
8
+ case length digits of
9
+ 10 => if valid digits
10
+ then SOME (implode digits)
11
+ else NONE
12
+ | 11 => if hd digits = #"1"
13
+ then check (tl digits)
14
+ else NONE
15
+ | _ => NONE
16
+ in
17
+ check (List.filter Char.isDigit (explode text))
18
+ end
@@ -0,0 +1,2 @@
1
+ fun clean (text: string): string option =
2
+ raise Fail "'clean' is not implemented"
@@ -0,0 +1,50 @@
1
+ (* version 1.2.0 *)
2
+
3
+ use "testlib.sml";
4
+ use "phone-number.sml";
5
+
6
+ infixr |>
7
+ fun x |> f = f x
8
+
9
+ val testsuite =
10
+ describe "phone-number" [
11
+ describe "Cleanup user-entered phone numbers" [
12
+ test "cleans the number"
13
+ (fn _ => clean ("(223) 456-7890") |> Expect.equalTo (SOME "2234567890")),
14
+
15
+ test "cleans numbers with dots"
16
+ (fn _ => clean ("223.456.7890") |> Expect.equalTo (SOME "2234567890")),
17
+
18
+ test "cleans numbers with multiple spaces"
19
+ (fn _ => clean ("223 456 7890 ") |> Expect.equalTo (SOME "2234567890")),
20
+
21
+ test "invalid when 9 digits"
22
+ (fn _ => clean ("123456789") |> Expect.equalTo NONE),
23
+
24
+ test "invalid when 11 digits does not start with a 1"
25
+ (fn _ => clean ("22234567890") |> Expect.equalTo NONE),
26
+
27
+ test "valid when 11 digits and starting with 1"
28
+ (fn _ => clean ("12234567890") |> Expect.equalTo (SOME "2234567890")),
29
+
30
+ test "valid when 11 digits and starting with 1 even with punctuation"
31
+ (fn _ => clean ("+1 (223) 456-7890") |> Expect.equalTo (SOME "2234567890")),
32
+
33
+ test "invalid when more than 11 digits"
34
+ (fn _ => clean ("321234567890") |> Expect.equalTo NONE),
35
+
36
+ test "invalid with letters"
37
+ (fn _ => clean ("123-abc-7890") |> Expect.equalTo NONE),
38
+
39
+ test "invalid with punctuations"
40
+ (fn _ => clean ("123-@:!-7890") |> Expect.equalTo NONE),
41
+
42
+ test "invalid if area code does not start with 2-9"
43
+ (fn _ => clean ("(123) 456-7890") |> Expect.equalTo NONE),
44
+
45
+ test "invalid if exchange code does not start with 2-9"
46
+ (fn _ => clean ("(223) 056-7890") |> Expect.equalTo NONE)
47
+ ]
48
+ ]
49
+
50
+ 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,79 @@
1
+ # Roman Numerals
2
+
3
+ Write a function to convert from normal numbers to Roman Numerals.
4
+
5
+ The Romans were a clever bunch. They conquered most of Europe and ruled
6
+ it for hundreds of years. They invented concrete and straight roads and
7
+ even bikinis. One thing they never discovered though was the number
8
+ zero. This made writing and dating extensive histories of their exploits
9
+ slightly more challenging, but the system of numbers they came up with
10
+ is still in use today. For example the BBC uses Roman numerals to date
11
+ their programmes.
12
+
13
+ The Romans wrote numbers using letters - I, V, X, L, C, D, M. (notice
14
+ these letters have lots of straight lines and are hence easy to hack
15
+ into stone tablets).
16
+
17
+ ```
18
+ 1 => I
19
+ 10 => X
20
+ 7 => VII
21
+ ```
22
+
23
+ There is no need to be able to convert numbers larger than about 3000.
24
+ (The Romans themselves didn't tend to go any higher)
25
+
26
+ Wikipedia says: Modern Roman numerals ... are written by expressing each
27
+ digit separately starting with the left most digit and skipping any
28
+ digit with a value of zero.
29
+
30
+ To see this in practice, consider the example of 1990.
31
+
32
+ In Roman numerals 1990 is MCMXC:
33
+
34
+ 1000=M
35
+ 900=CM
36
+ 90=XC
37
+
38
+ 2008 is written as MMVIII:
39
+
40
+ 2000=MM
41
+ 8=VIII
42
+
43
+ See also: http://www.novaroma.org/via_romana/numbers.html
44
+
45
+ ## Loading your exercise implementation in PolyML
46
+
47
+ ```
48
+ $ poly --use {exercise}.sml
49
+ ```
50
+
51
+ Or:
52
+
53
+ ```
54
+ $ poly
55
+ > use "{exercise}.sml";
56
+ ```
57
+
58
+ **Note:** You have to replace {exercise}.
59
+
60
+ ## Running the tests
61
+
62
+ ```
63
+ $ poly -q --use test.sml
64
+ ```
65
+
66
+ ## Feedback, Issues, Pull Requests
67
+
68
+ The [exercism/sml](https://github.com/exercism/sml) repository on
69
+ GitHub is the home for all of the Standard ML exercises.
70
+
71
+ If you have feedback about an exercise, or want to help implementing a new
72
+ one, head over there and create an issue. We'll do our best to help you!
73
+
74
+ ## Source
75
+
76
+ The Roman Numeral Kata [http://codingdojo.org/cgi-bin/index.pl?KataRomanNumerals](http://codingdojo.org/cgi-bin/index.pl?KataRomanNumerals)
77
+
78
+ ## Submitting Incomplete Solutions
79
+ It's possible to submit an incomplete solution so you can see how others have completed the exercise.