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,27 @@
1
+ fun roman number =
2
+ let
3
+ val pairs = [
4
+ (1000, "M"),
5
+ (900 , "CM"),
6
+ (500 , "D"),
7
+ (400 , "CD"),
8
+ (100 , "C"),
9
+ (90 , "XC"),
10
+ (50 , "L"),
11
+ (40 , "XL"),
12
+ (10 , "X"),
13
+ (9 , "IX"),
14
+ (5 , "V"),
15
+ (4 , "IV"),
16
+ (1 , "I")
17
+ ]
18
+
19
+ fun loop 0 _ = []
20
+ | loop _ [] = []
21
+ | loop n (ps as ((num, rep) :: ps')) =
22
+ if n < num
23
+ then loop n ps'
24
+ else rep :: loop (n - num) ps
25
+ in
26
+ concat (loop number pairs)
27
+ end
@@ -0,0 +1,2 @@
1
+ fun roman (number: int): string =
2
+ raise Fail "'roman' is not implemented"
@@ -0,0 +1,66 @@
1
+ (* version 1.0.0 *)
2
+
3
+ use "testlib.sml";
4
+ use "roman-numerals.sml";
5
+
6
+ infixr |>
7
+ fun x |> f = f x
8
+
9
+ val testsuite =
10
+ describe "roman-numerals" [
11
+ test "1 is a single I"
12
+ (fn _ => roman (1) |> Expect.equalTo "I"),
13
+
14
+ test "2 is two I's"
15
+ (fn _ => roman (2) |> Expect.equalTo "II"),
16
+
17
+ test "3 is three I's"
18
+ (fn _ => roman (3) |> Expect.equalTo "III"),
19
+
20
+ test "4, being 5 - 1, is IV"
21
+ (fn _ => roman (4) |> Expect.equalTo "IV"),
22
+
23
+ test "5 is a single V"
24
+ (fn _ => roman (5) |> Expect.equalTo "V"),
25
+
26
+ test "6, being 5 + 1, is VI"
27
+ (fn _ => roman (6) |> Expect.equalTo "VI"),
28
+
29
+ test "9, being 10 - 1, is IX"
30
+ (fn _ => roman (9) |> Expect.equalTo "IX"),
31
+
32
+ test "20 is two X's"
33
+ (fn _ => roman (27) |> Expect.equalTo "XXVII"),
34
+
35
+ test "48 is not 50 - 2 but rather 40 + 8"
36
+ (fn _ => roman (48) |> Expect.equalTo "XLVIII"),
37
+
38
+ test "50 is a single L"
39
+ (fn _ => roman (59) |> Expect.equalTo "LIX"),
40
+
41
+ test "90, being 100 - 10, is XC"
42
+ (fn _ => roman (93) |> Expect.equalTo "XCIII"),
43
+
44
+ test "100 is a single C"
45
+ (fn _ => roman (141) |> Expect.equalTo "CXLI"),
46
+
47
+ test "60, being 50 + 10, is LX"
48
+ (fn _ => roman (163) |> Expect.equalTo "CLXIII"),
49
+
50
+ test "400, being 500 - 100, is CD"
51
+ (fn _ => roman (402) |> Expect.equalTo "CDII"),
52
+
53
+ test "500 is a single D"
54
+ (fn _ => roman (575) |> Expect.equalTo "DLXXV"),
55
+
56
+ test "900, being 1000 - 100, is CM"
57
+ (fn _ => roman (911) |> Expect.equalTo "CMXI"),
58
+
59
+ test "1000 is a single M"
60
+ (fn _ => roman (1024) |> Expect.equalTo "MXXIV"),
61
+
62
+ test "3000 is three M's"
63
+ (fn _ => roman (3000) |> Expect.equalTo "MMM")
64
+ ]
65
+
66
+ 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)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trackler
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.1.36
4
+ version: 2.2.1.37
5
5
  platform: ruby
6
6
  authors:
7
7
  - Katrina Owen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-09-23 00:00:00.000000000 Z
11
+ date: 2017-09-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubyzip
@@ -10906,6 +10906,7 @@ files:
10906
10906
  - tracks/rust/docs/RESOURCES.md
10907
10907
  - tracks/rust/docs/SNIPPET.txt
10908
10908
  - tracks/rust/docs/TESTS.md
10909
+ - tracks/rust/exercises/accumulate/.gitignore
10909
10910
  - tracks/rust/exercises/accumulate/.meta/hints.md
10910
10911
  - tracks/rust/exercises/accumulate/Cargo.lock
10911
10912
  - tracks/rust/exercises/accumulate/Cargo.toml
@@ -10990,6 +10991,7 @@ files:
10990
10991
  - tracks/rust/exercises/circular-buffer/example.rs
10991
10992
  - tracks/rust/exercises/circular-buffer/src/lib.rs
10992
10993
  - tracks/rust/exercises/circular-buffer/tests/circular-buffer.rs
10994
+ - tracks/rust/exercises/clock/.gitignore
10993
10995
  - tracks/rust/exercises/clock/.meta/hints.md
10994
10996
  - tracks/rust/exercises/clock/Cargo.lock
10995
10997
  - tracks/rust/exercises/clock/Cargo.toml
@@ -11124,6 +11126,7 @@ files:
11124
11126
  - tracks/rust/exercises/minesweeper/example.rs
11125
11127
  - tracks/rust/exercises/minesweeper/src/lib.rs
11126
11128
  - tracks/rust/exercises/minesweeper/tests/minesweeper.rs
11129
+ - tracks/rust/exercises/nth-prime/.gitignore
11127
11130
  - tracks/rust/exercises/nth-prime/Cargo.lock
11128
11131
  - tracks/rust/exercises/nth-prime/Cargo.toml
11129
11132
  - tracks/rust/exercises/nth-prime/README.md
@@ -11186,6 +11189,7 @@ files:
11186
11189
  - tracks/rust/exercises/phone-number/example.rs
11187
11190
  - tracks/rust/exercises/phone-number/src/lib.rs
11188
11191
  - tracks/rust/exercises/phone-number/tests/phone-number.rs
11192
+ - tracks/rust/exercises/pig-latin/.gitignore
11189
11193
  - tracks/rust/exercises/pig-latin/Cargo-example.toml
11190
11194
  - tracks/rust/exercises/pig-latin/Cargo.lock
11191
11195
  - tracks/rust/exercises/pig-latin/Cargo.toml
@@ -11201,6 +11205,7 @@ files:
11201
11205
  - tracks/rust/exercises/poker/example.rs
11202
11206
  - tracks/rust/exercises/poker/src/lib.rs
11203
11207
  - tracks/rust/exercises/poker/tests/poker.rs
11208
+ - tracks/rust/exercises/prime-factors/.gitignore
11204
11209
  - tracks/rust/exercises/prime-factors/Cargo.lock
11205
11210
  - tracks/rust/exercises/prime-factors/Cargo.toml
11206
11211
  - tracks/rust/exercises/prime-factors/README.md
@@ -11214,12 +11219,14 @@ files:
11214
11219
  - tracks/rust/exercises/protein-translation/example.rs
11215
11220
  - tracks/rust/exercises/protein-translation/src/lib.rs
11216
11221
  - tracks/rust/exercises/protein-translation/tests/proteins.rs
11222
+ - tracks/rust/exercises/proverb/.gitignore
11217
11223
  - tracks/rust/exercises/proverb/Cargo.lock
11218
11224
  - tracks/rust/exercises/proverb/Cargo.toml
11219
11225
  - tracks/rust/exercises/proverb/README.md
11220
11226
  - tracks/rust/exercises/proverb/example.rs
11221
11227
  - tracks/rust/exercises/proverb/src/lib.rs
11222
11228
  - tracks/rust/exercises/proverb/tests/proverb.rs
11229
+ - tracks/rust/exercises/pythagorean-triplet/.gitignore
11223
11230
  - tracks/rust/exercises/pythagorean-triplet/Cargo.lock
11224
11231
  - tracks/rust/exercises/pythagorean-triplet/Cargo.toml
11225
11232
  - tracks/rust/exercises/pythagorean-triplet/README.md
@@ -11289,12 +11296,14 @@ files:
11289
11296
  - tracks/rust/exercises/rotational-cipher/example.rs
11290
11297
  - tracks/rust/exercises/rotational-cipher/src/lib.rs
11291
11298
  - tracks/rust/exercises/rotational-cipher/tests/rotational-cipher.rs
11299
+ - tracks/rust/exercises/run-length-encoding/.gitignore
11292
11300
  - tracks/rust/exercises/run-length-encoding/Cargo.lock
11293
11301
  - tracks/rust/exercises/run-length-encoding/Cargo.toml
11294
11302
  - tracks/rust/exercises/run-length-encoding/README.md
11295
11303
  - tracks/rust/exercises/run-length-encoding/example.rs
11296
11304
  - tracks/rust/exercises/run-length-encoding/src/lib.rs
11297
11305
  - tracks/rust/exercises/run-length-encoding/tests/run-length-encoding.rs
11306
+ - tracks/rust/exercises/say/.gitignore
11298
11307
  - tracks/rust/exercises/say/.meta/hints.md
11299
11308
  - tracks/rust/exercises/say/Cargo.lock
11300
11309
  - tracks/rust/exercises/say/Cargo.toml
@@ -11624,7 +11633,7 @@ files:
11624
11633
  - tracks/scala/exercises/nucleotide-count/README.md
11625
11634
  - tracks/scala/exercises/nucleotide-count/build.sbt
11626
11635
  - tracks/scala/exercises/nucleotide-count/example.scala
11627
- - tracks/scala/exercises/nucleotide-count/src/main/scala/DNA.scala
11636
+ - tracks/scala/exercises/nucleotide-count/src/main/scala/.keep
11628
11637
  - tracks/scala/exercises/nucleotide-count/src/test/scala/NucleotideCountTest.scala
11629
11638
  - tracks/scala/exercises/ocr-numbers/README.md
11630
11639
  - tracks/scala/exercises/ocr-numbers/build.sbt
@@ -11858,6 +11867,7 @@ files:
11858
11867
  - tracks/scala/testgen/src/main/scala/BowlingTestGenerator.scala
11859
11868
  - tracks/scala/testgen/src/main/scala/BracketPushTestGenerator.scala
11860
11869
  - tracks/scala/testgen/src/main/scala/ChangeTestGenerator.scala
11870
+ - tracks/scala/testgen/src/main/scala/ClockTestGenerator.scala
11861
11871
  - tracks/scala/testgen/src/main/scala/ConnectTestGenerator.scala
11862
11872
  - tracks/scala/testgen/src/main/scala/CryptoSquareTestGenerator.scala
11863
11873
  - tracks/scala/testgen/src/main/scala/CustomSetTestGenerator.scala
@@ -11865,18 +11875,21 @@ files:
11865
11875
  - tracks/scala/testgen/src/main/scala/DominoesTestGenerator.scala
11866
11876
  - tracks/scala/testgen/src/main/scala/EtlTestGenerator.scala
11867
11877
  - tracks/scala/testgen/src/main/scala/FoodChainTestGenerator.scala
11878
+ - tracks/scala/testgen/src/main/scala/ForthTestGenerator.scala
11868
11879
  - tracks/scala/testgen/src/main/scala/GigasecondTestGenerator.scala
11869
11880
  - tracks/scala/testgen/src/main/scala/GrainsTestGenerator.scala
11870
11881
  - tracks/scala/testgen/src/main/scala/HammingTestGenerator.scala
11871
11882
  - tracks/scala/testgen/src/main/scala/HelloWorldTestGenerator.scala
11872
11883
  - tracks/scala/testgen/src/main/scala/HouseTestGenerator.scala
11873
11884
  - tracks/scala/testgen/src/main/scala/IsogramTestGenerator.scala
11885
+ - tracks/scala/testgen/src/main/scala/KindergartenGardenTestGenerator.scala
11874
11886
  - tracks/scala/testgen/src/main/scala/LeapTestGenerator.scala
11875
11887
  - tracks/scala/testgen/src/main/scala/LuhnTestGenerator.scala
11876
11888
  - tracks/scala/testgen/src/main/scala/MinesweeperTestGenerator.scala
11877
11889
  - tracks/scala/testgen/src/main/scala/NthPrimeTestGenerator.scala
11878
11890
  - tracks/scala/testgen/src/main/scala/NucleotideCountTestGenerator.scala
11879
11891
  - tracks/scala/testgen/src/main/scala/OcrNumbersTestGenerator.scala
11892
+ - tracks/scala/testgen/src/main/scala/PalindromeProductsTestGenerator.scala
11880
11893
  - tracks/scala/testgen/src/main/scala/PangramsTestGenerator.scala
11881
11894
  - tracks/scala/testgen/src/main/scala/PascalsTriangleTestGenerator.scala
11882
11895
  - tracks/scala/testgen/src/main/scala/PerfectNumbersTestGenerator.scala
@@ -12076,6 +12089,11 @@ files:
12076
12089
  - tracks/sml/exercises/perfect-numbers/perfect-numbers.sml
12077
12090
  - tracks/sml/exercises/perfect-numbers/test.sml
12078
12091
  - tracks/sml/exercises/perfect-numbers/testlib.sml
12092
+ - tracks/sml/exercises/phone-number/README.md
12093
+ - tracks/sml/exercises/phone-number/example.sml
12094
+ - tracks/sml/exercises/phone-number/phone-number.sml
12095
+ - tracks/sml/exercises/phone-number/test.sml
12096
+ - tracks/sml/exercises/phone-number/testlib.sml
12079
12097
  - tracks/sml/exercises/prime-factors/README.md
12080
12098
  - tracks/sml/exercises/prime-factors/example.sml
12081
12099
  - tracks/sml/exercises/prime-factors/prime-factors.sml
@@ -12090,6 +12108,11 @@ files:
12090
12108
  - tracks/sml/exercises/rna-transcription/rna-transcription.sml
12091
12109
  - tracks/sml/exercises/rna-transcription/test.sml
12092
12110
  - tracks/sml/exercises/rna-transcription/testlib.sml
12111
+ - tracks/sml/exercises/roman-numerals/README.md
12112
+ - tracks/sml/exercises/roman-numerals/example.sml
12113
+ - tracks/sml/exercises/roman-numerals/roman-numerals.sml
12114
+ - tracks/sml/exercises/roman-numerals/test.sml
12115
+ - tracks/sml/exercises/roman-numerals/testlib.sml
12093
12116
  - tracks/sml/exercises/sum-of-multiples/README.md
12094
12117
  - tracks/sml/exercises/sum-of-multiples/example.sml
12095
12118
  - tracks/sml/exercises/sum-of-multiples/sum-of-multiples.sml
@@ -1,6 +0,0 @@
1
- class DNA(dna: String) {
2
-
3
- def count(char: Char): Either[String, Int] = ???
4
-
5
- def nucleotideCounts: Either[String, Map[Char, Int]] = ???
6
- }