trackler 2.0.6.3 → 2.0.6.4
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.
- checksums.yaml +4 -4
- data/lib/trackler/version.rb +1 -1
- data/tracks/go/config.json +6 -1
- data/tracks/java/exercises/atbash-cipher/src/test/java/AtbashTest.java +7 -7
- data/tracks/perl6/config.json +5 -0
- data/tracks/perl6/exercises/atbash-cipher/Example.p6 +12 -0
- data/tracks/perl6/exercises/atbash-cipher/cases.json +82 -0
- data/tracks/perl6/exercises/atbash-cipher/cipher.t +36 -0
- data/tracks/rust/config.json +1 -0
- data/tracks/rust/exercises/nucleotide-count/example.rs +17 -6
- data/tracks/rust/exercises/nucleotide-count/tests/nucleotide-count.rs +34 -4
- data/tracks/rust/problems.md +1 -1
- data/tracks/scala/config.json +12 -0
- data/tracks/scala/exercises/acronym/example.scala +2 -2
- data/tracks/scala/exercises/acronym/src/main/scala/Acronym.scala +2 -2
- data/tracks/scala/exercises/acronym/src/test/scala/AcronymTest.scala +1 -1
- data/tracks/scala/exercises/roman-numerals/build.sbt +2 -2
- data/tracks/scala/exercises/roman-numerals/example.scala +5 -7
- data/tracks/scala/exercises/roman-numerals/src/test/scala/RomanNumeralsTest.scala +18 -18
- data/tracks/scala/exercises/run-length-encoding/build.sbt +3 -0
- data/tracks/scala/exercises/run-length-encoding/example.scala +32 -0
- data/tracks/scala/exercises/run-length-encoding/src/main/scala/RunLengthEncoding.scala +6 -0
- data/tracks/scala/exercises/run-length-encoding/src/test/scala/RunLengthEncodingTests.scala +52 -0
- metadata +9 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b6aba1544337c241fe655409dc6f50da3ec7b21a
|
|
4
|
+
data.tar.gz: 9e50e4e647c05032ada9d09a96130d2543b7a20e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 607f0c63e16fa33ba4d4dce2389451ed73afc0770e7bdb5dde7181a01047ed1474dfac5bcbdc50b3842eec47242f58dcee14d05abfc968b6c022a06c956ae506
|
|
7
|
+
data.tar.gz: 5c2b8db8780598b58ad8a09c4637dccdb264841f5746e0c82f66d864b10c5483a6703edc04a9a307cf35dd14b2ad7833a7d49762d14e1c534a69a1c46580ebdb
|
data/lib/trackler/version.rb
CHANGED
data/tracks/go/config.json
CHANGED
|
@@ -45,10 +45,10 @@ public class AtbashTest {
|
|
|
45
45
|
|
|
46
46
|
@RunWith(Parameterized.class)
|
|
47
47
|
public static class DecodeTest {
|
|
48
|
-
private String
|
|
49
|
-
private String
|
|
48
|
+
private String ciphertext;
|
|
49
|
+
private String plaintext;
|
|
50
50
|
|
|
51
|
-
@Parameters
|
|
51
|
+
@Parameters(name = "{index}: expected ciphertext \"{0}\" to decode to plaintext \"{1}\".")
|
|
52
52
|
public static Collection<Object[]> data() {
|
|
53
53
|
return Arrays.asList(new Object[][] {
|
|
54
54
|
{ "vcvix rhn", "exercism" },
|
|
@@ -57,15 +57,15 @@ public class AtbashTest {
|
|
|
57
57
|
});
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
public DecodeTest(String
|
|
61
|
-
this.
|
|
62
|
-
this.
|
|
60
|
+
public DecodeTest(String ciphertext, String plaintext) {
|
|
61
|
+
this.ciphertext = ciphertext;
|
|
62
|
+
this.plaintext = plaintext;
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
@Ignore
|
|
66
66
|
@Test
|
|
67
67
|
public void test() {
|
|
68
|
-
assertEquals(
|
|
68
|
+
assertEquals(plaintext, Atbash.decode(ciphertext));
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
}
|
data/tracks/perl6/config.json
CHANGED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
sub encode($input) is export {
|
|
2
|
+
decode($input.lc.trans( ['a'..'z', 0..9] => '', :complement ) )
|
|
3
|
+
.comb(5)
|
|
4
|
+
.join: ' ';
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
sub decode (Str $input) is export {
|
|
8
|
+
return $input
|
|
9
|
+
.lc
|
|
10
|
+
.subst( /\W/, '', :g )
|
|
11
|
+
.trans( [ 'a'..'z' ] => ['a'..'z'].reverse );
|
|
12
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
{
|
|
2
|
+
"#": [
|
|
3
|
+
"The tests are divided into two groups: ",
|
|
4
|
+
"* Encoding from English to atbash cipher",
|
|
5
|
+
"* Decoding from atbash cipher to all-lowercase-mashed-together English"
|
|
6
|
+
],
|
|
7
|
+
"encode": {
|
|
8
|
+
"description": ["Test encoding from English to atbash"],
|
|
9
|
+
"cases": [
|
|
10
|
+
{
|
|
11
|
+
"description": "encode yes",
|
|
12
|
+
"phrase": "yes",
|
|
13
|
+
"expected": "bvh"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"description": "encode no",
|
|
17
|
+
"phrase": "no",
|
|
18
|
+
"expected": "ml"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"description": "encode OMG",
|
|
22
|
+
"phrase": "OMG",
|
|
23
|
+
"expected": "lnt"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"description": "encode spaces",
|
|
27
|
+
"phrase": "O M G",
|
|
28
|
+
"expected": "lnt"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"description": "encode mindblowingly",
|
|
32
|
+
"phrase": "mindblowingly",
|
|
33
|
+
"expected": "nrmwy oldrm tob"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"description": "encode numbers",
|
|
37
|
+
"phrase": "Testing,1 2 3, testing.",
|
|
38
|
+
"expected": "gvhgr mt123 gvhgr mt"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"description": "encode deep thought",
|
|
42
|
+
"phrase": "Truth is fiction.",
|
|
43
|
+
"expected": "gifgs rhurx grlm"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"description": "encode all the letters",
|
|
47
|
+
"phrase": "The quick brown fox jumps over the lazy dog.",
|
|
48
|
+
"expected": "gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"description": "encode ignores non ascii",
|
|
52
|
+
"phrase": "non ascii éignored",
|
|
53
|
+
"expected": "mlmzh xrrrt mlivw"
|
|
54
|
+
}
|
|
55
|
+
]
|
|
56
|
+
},
|
|
57
|
+
"decode": {
|
|
58
|
+
"description": ["Test decoding from atbash to English"],
|
|
59
|
+
"cases": [
|
|
60
|
+
{
|
|
61
|
+
"description": "decode exercism",
|
|
62
|
+
"phrase": "vcvix rhn",
|
|
63
|
+
"expected": "exercism"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"description": "decode a sentence",
|
|
67
|
+
"phrase": "zmlyh gzxov rhlug vmzhg vkkrm thglm v",
|
|
68
|
+
"expected": "anobstacleisoftenasteppingstone"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"description": "decode numbers",
|
|
72
|
+
"phrase": "gvhgr mt123 gvhgr mt",
|
|
73
|
+
"expected": "testing123testing"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"description": "decode all the letters",
|
|
77
|
+
"phrase": "gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt",
|
|
78
|
+
"expected": "thequickbrownfoxjumpsoverthelazydog"
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env perl6
|
|
2
|
+
|
|
3
|
+
use Test;
|
|
4
|
+
use JSON::Tiny;
|
|
5
|
+
|
|
6
|
+
use lib ( my $dir = IO::Path.new($?FILE).parent ).path;
|
|
7
|
+
|
|
8
|
+
my $module_name = %*ENV<EXERCISM>.so ?? 'Example' !! 'Allergies';
|
|
9
|
+
my @potential_module = <p6 pm6 pm>.map: $module_name ~ '.' ~ *;
|
|
10
|
+
|
|
11
|
+
my $module = first { $dir.child($_).e }, |@potential_module
|
|
12
|
+
or die "No file '$module_name.p6' found\n";
|
|
13
|
+
|
|
14
|
+
require $module <&encode &decode>;
|
|
15
|
+
|
|
16
|
+
plan 2;
|
|
17
|
+
|
|
18
|
+
my %cases = from-json $dir.child('cases.json').slurp;
|
|
19
|
+
|
|
20
|
+
subtest 'encode' => {
|
|
21
|
+
my @cases = |%cases.<encode>.<cases>;
|
|
22
|
+
|
|
23
|
+
plan +@cases;
|
|
24
|
+
|
|
25
|
+
is encode( .<phrase> ), .<expected>, .<description>
|
|
26
|
+
for @cases;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
subtest 'decode' => {
|
|
30
|
+
my @cases = |%cases.<decode>.<cases>;
|
|
31
|
+
|
|
32
|
+
plan +@cases;
|
|
33
|
+
|
|
34
|
+
is decode( .<phrase> ), .<expected>, .<description>
|
|
35
|
+
for @cases;
|
|
36
|
+
};
|
data/tracks/rust/config.json
CHANGED
|
@@ -1,13 +1,24 @@
|
|
|
1
1
|
use std::collections::HashMap;
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
static VALID_NUCLEOTIDES: &'static str = "ACGT";
|
|
4
|
+
|
|
5
|
+
pub fn count(nucleotide: char, input: &str) -> Result<usize, char> {
|
|
6
|
+
let valid = |x: char| { VALID_NUCLEOTIDES.contains(x) };
|
|
7
|
+
if valid(nucleotide) && input.chars().all(valid) {
|
|
8
|
+
Ok(input.chars().filter(|&c| c == nucleotide).count())
|
|
9
|
+
} else {
|
|
10
|
+
Err(nucleotide)
|
|
11
|
+
}
|
|
5
12
|
}
|
|
6
13
|
|
|
7
|
-
pub fn nucleotide_counts(input: &str) -> HashMap<char, usize> {
|
|
8
|
-
let mut map: HashMap<char, usize> =
|
|
14
|
+
pub fn nucleotide_counts(input: &str) -> Result<HashMap<char, usize>, char> {
|
|
15
|
+
let mut map: HashMap<char, usize> = VALID_NUCLEOTIDES.chars().map(|c| (c, 0)).collect();
|
|
9
16
|
for nucleotide in input.chars() {
|
|
10
|
-
|
|
17
|
+
if let Some(n) = map.get_mut(&nucleotide) {
|
|
18
|
+
*n += 1;
|
|
19
|
+
} else {
|
|
20
|
+
return Err(nucleotide);
|
|
21
|
+
}
|
|
11
22
|
}
|
|
12
|
-
map
|
|
23
|
+
Ok(map)
|
|
13
24
|
}
|
|
@@ -7,7 +7,7 @@ fn check_dna(s: &str, pairs: &[(char, usize)]) {
|
|
|
7
7
|
// message for assert_eq! is as informative as possible. A simpler
|
|
8
8
|
// solution would simply check the length of the map, and then
|
|
9
9
|
// check for the presence and value of each key in the given pairs vector.
|
|
10
|
-
let mut m: HashMap<char, usize> = dna::nucleotide_counts(s);
|
|
10
|
+
let mut m: HashMap<char, usize> = dna::nucleotide_counts(s).unwrap();
|
|
11
11
|
for &(k, v) in pairs.iter() {
|
|
12
12
|
assert_eq!((k, m.remove(&k).unwrap()), (k, v));
|
|
13
13
|
}
|
|
@@ -16,20 +16,44 @@ fn check_dna(s: &str, pairs: &[(char, usize)]) {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
#[test]
|
|
19
|
+
fn count_returns_result() {
|
|
20
|
+
assert!(dna::count('A', "").is_ok());
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
#[test]
|
|
24
|
+
#[ignore]
|
|
19
25
|
fn test_count_empty() {
|
|
20
|
-
assert_eq!(dna::count('A', ""), 0);
|
|
26
|
+
assert_eq!(dna::count('A', "").unwrap(), 0);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
#[test]
|
|
30
|
+
#[ignore]
|
|
31
|
+
fn count_invalid_nucleotide() {
|
|
32
|
+
assert!(dna::count('X', "A").is_err());
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
#[test]
|
|
36
|
+
#[ignore]
|
|
37
|
+
fn count_invalid_dna() {
|
|
38
|
+
assert!(dna::count('A', "AX").is_err());
|
|
21
39
|
}
|
|
22
40
|
|
|
23
41
|
#[test]
|
|
24
42
|
#[ignore]
|
|
25
43
|
fn test_count_repetitive_cytosine() {
|
|
26
|
-
assert_eq!(dna::count('C', "CCCCC"), 5);
|
|
44
|
+
assert_eq!(dna::count('C', "CCCCC").unwrap(), 5);
|
|
27
45
|
}
|
|
28
46
|
|
|
29
47
|
#[test]
|
|
30
48
|
#[ignore]
|
|
31
49
|
fn test_count_only_thymine() {
|
|
32
|
-
assert_eq!(dna::count('T', "GGGGGTAACCCGG"), 1);
|
|
50
|
+
assert_eq!(dna::count('T', "GGGGGTAACCCGG").unwrap(), 1);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
#[test]
|
|
54
|
+
#[ignore]
|
|
55
|
+
fn counts_returns_result() {
|
|
56
|
+
assert!(dna::nucleotide_counts("ACGT").is_ok());
|
|
33
57
|
}
|
|
34
58
|
|
|
35
59
|
#[test]
|
|
@@ -56,3 +80,9 @@ fn test_nucleotide_count_counts_all() {
|
|
|
56
80
|
GAGTGTCTGATAGCAGC",
|
|
57
81
|
&[('A', 20), ('T', 21), ('C', 12), ('G', 17)]);
|
|
58
82
|
}
|
|
83
|
+
|
|
84
|
+
#[test]
|
|
85
|
+
#[ignore]
|
|
86
|
+
fn counts_invalid_nucleotide_results_in_err() {
|
|
87
|
+
assert!(dna::nucleotide_counts("GGXXX").is_err());
|
|
88
|
+
}
|
data/tracks/rust/problems.md
CHANGED
|
@@ -36,7 +36,7 @@ hamming | Result
|
|
|
36
36
|
pascals-triangle | Math, Vec, Index (optional)
|
|
37
37
|
scrabble-score | chaining higher-order functions, HashMap (optional)
|
|
38
38
|
pangram | filter, ascii (optional)
|
|
39
|
-
nucleotide-count | filter, entry api, mutablity, match
|
|
39
|
+
nucleotide-count | Result, filter, entry api, mutablity, match
|
|
40
40
|
largest-series-product | Result, windows, higher-order functions, char
|
|
41
41
|
word-count | hashmap, str vs string, chars, entry api
|
|
42
42
|
atbash-cipher | str vs string, primitive types, iterators, chars, ascii
|
data/tracks/scala/config.json
CHANGED
|
@@ -28,6 +28,15 @@
|
|
|
28
28
|
"Sets"
|
|
29
29
|
]
|
|
30
30
|
},
|
|
31
|
+
{
|
|
32
|
+
"slug": "run-length-encoding",
|
|
33
|
+
"difficulty": 1,
|
|
34
|
+
"topics": [
|
|
35
|
+
"Algorithms",
|
|
36
|
+
"Transforming",
|
|
37
|
+
"Strings"
|
|
38
|
+
]
|
|
39
|
+
},
|
|
31
40
|
{
|
|
32
41
|
"slug": "hamming",
|
|
33
42
|
"difficulty": 2,
|
|
@@ -158,6 +167,9 @@
|
|
|
158
167
|
"slug": "roman-numerals",
|
|
159
168
|
"difficulty": 1,
|
|
160
169
|
"topics": [
|
|
170
|
+
"Sequences",
|
|
171
|
+
"Algorithms",
|
|
172
|
+
"Transforming"
|
|
161
173
|
]
|
|
162
174
|
},
|
|
163
175
|
{
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
def abbreviate: String = ???
|
|
1
|
+
object Acronym {
|
|
2
|
+
def abbreviate(phrase: String): String = ???
|
|
3
3
|
}
|
|
@@ -10,6 +10,6 @@ class AcronymTest extends FlatSpec with Matchers {
|
|
|
10
10
|
("Complementary metal-oxide semiconductor", "CMOS"))
|
|
11
11
|
|
|
12
12
|
it should "create acronyms" in {
|
|
13
|
-
acronyms.foreach{case (phrase, acronym) => Acronym(phrase)
|
|
13
|
+
acronyms.foreach{case (phrase, acronym) => Acronym.abbreviate(phrase) should equal(acronym)}
|
|
14
14
|
}
|
|
15
15
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
scalaVersion := "2.
|
|
1
|
+
scalaVersion := "2.12.1"
|
|
2
2
|
|
|
3
|
-
libraryDependencies += "org.scalatest"
|
|
3
|
+
libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.1" % "test"
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import scala.annotation.tailrec
|
|
1
2
|
import scala.collection.immutable.ListMap
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
object RomanNumeral {
|
|
4
5
|
private def numeralValues = ListMap(
|
|
5
6
|
1000 -> "M",
|
|
6
7
|
900 -> "CM",
|
|
@@ -17,16 +18,13 @@ class RomanNumeral(n: Int) {
|
|
|
17
18
|
1 -> "I"
|
|
18
19
|
)
|
|
19
20
|
|
|
21
|
+
def toNumerals(n: Int) = fromNumber(n, "")
|
|
22
|
+
|
|
23
|
+
@tailrec
|
|
20
24
|
private def fromNumber(n: Int, numerals: String): String = {
|
|
21
25
|
numeralValues.find(_._1 <= n) match {
|
|
22
26
|
case Some((threshold, numeral)) => fromNumber(n - threshold, numerals + numeral)
|
|
23
27
|
case None => numerals
|
|
24
28
|
}
|
|
25
29
|
}
|
|
26
|
-
|
|
27
|
-
val value = fromNumber(n, "")
|
|
28
30
|
}
|
|
29
|
-
|
|
30
|
-
object RomanNumeral {
|
|
31
|
-
def apply(n: Int) = new RomanNumeral(n)
|
|
32
|
-
}
|
|
@@ -3,91 +3,91 @@ import org.scalatest._
|
|
|
3
3
|
class RomanNumeralsSpecs extends FunSpec with Matchers {
|
|
4
4
|
|
|
5
5
|
it ("0 equals empty string") {
|
|
6
|
-
RomanNumeral(0)
|
|
6
|
+
RomanNumeral.toNumerals(0) should be ("")
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
it ("1 equals I") {
|
|
10
10
|
pending
|
|
11
|
-
RomanNumeral(1)
|
|
11
|
+
RomanNumeral.toNumerals(1) should be ("I")
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
it ("2 equals II") {
|
|
15
15
|
pending
|
|
16
|
-
RomanNumeral(2)
|
|
16
|
+
RomanNumeral.toNumerals(2) should be ("II")
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
it ("3 equals III") {
|
|
20
20
|
pending
|
|
21
|
-
RomanNumeral(3)
|
|
21
|
+
RomanNumeral.toNumerals(3) should be ("III")
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
it ("4 equals IV") {
|
|
25
25
|
pending
|
|
26
|
-
RomanNumeral(4)
|
|
26
|
+
RomanNumeral.toNumerals(4) should be ("IV")
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
it ("5 equals V") {
|
|
30
30
|
pending
|
|
31
|
-
RomanNumeral(5)
|
|
31
|
+
RomanNumeral.toNumerals(5) should be ("V")
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
it ("6 equals VI") {
|
|
35
35
|
pending
|
|
36
|
-
RomanNumeral(6)
|
|
36
|
+
RomanNumeral.toNumerals(6) should be ("VI")
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
it ("9 equals IX") {
|
|
40
40
|
pending
|
|
41
|
-
RomanNumeral(9)
|
|
41
|
+
RomanNumeral.toNumerals(9) should be ("IX")
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
it ("27 equals XXVII") {
|
|
45
45
|
pending
|
|
46
|
-
RomanNumeral(27)
|
|
46
|
+
RomanNumeral.toNumerals(27) should be ("XXVII")
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
it ("48 equals XLVIII") {
|
|
50
50
|
pending
|
|
51
|
-
RomanNumeral(48)
|
|
51
|
+
RomanNumeral.toNumerals(48) should be ("XLVIII")
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
it ("59 equals LIX") {
|
|
55
55
|
pending
|
|
56
|
-
RomanNumeral(59)
|
|
56
|
+
RomanNumeral.toNumerals(59) should be ("LIX")
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
it ("93 equals XCIII") {
|
|
60
60
|
pending
|
|
61
|
-
RomanNumeral(93)
|
|
61
|
+
RomanNumeral.toNumerals(93) should be ("XCIII")
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
it ("141 equals CXLI") {
|
|
65
65
|
pending
|
|
66
|
-
RomanNumeral(141)
|
|
66
|
+
RomanNumeral.toNumerals(141) should be ("CXLI")
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
it ("402 equals CDII") {
|
|
70
70
|
pending
|
|
71
|
-
RomanNumeral(402)
|
|
71
|
+
RomanNumeral.toNumerals(402) should be ("CDII")
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
it ("575 equals DLXXV") {
|
|
75
75
|
pending
|
|
76
|
-
RomanNumeral(575)
|
|
76
|
+
RomanNumeral.toNumerals(575) should be ("DLXXV")
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
it ("911 equals CMXI") {
|
|
80
80
|
pending
|
|
81
|
-
RomanNumeral(911)
|
|
81
|
+
RomanNumeral.toNumerals(911) should be ("CMXI")
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
it ("1024 equals MXXIV") {
|
|
85
85
|
pending
|
|
86
|
-
RomanNumeral(1024)
|
|
86
|
+
RomanNumeral.toNumerals(1024) should be ("MXXIV")
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
it ("3000 equals MMM") {
|
|
90
90
|
pending
|
|
91
|
-
RomanNumeral(3000)
|
|
91
|
+
RomanNumeral.toNumerals(3000) should be ("MMM")
|
|
92
92
|
}
|
|
93
93
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
object RunLengthEncoding {
|
|
2
|
+
type Plain = String
|
|
3
|
+
type Encoded = String
|
|
4
|
+
|
|
5
|
+
def encode(str: Plain): Encoded = {
|
|
6
|
+
def encodeGroup(xs: Seq[Char]): Seq[Char] =
|
|
7
|
+
if (xs.length > 1) s"${xs.length}${xs.head}"
|
|
8
|
+
else xs mkString
|
|
9
|
+
|
|
10
|
+
splitByEquals(str) flatMap encodeGroup mkString
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
def decode(str: Encoded): Plain = {
|
|
14
|
+
val nextChar: ((Int, Seq[Char]), Char) => (Int, Seq[Char]) = {
|
|
15
|
+
case ((n, xs), x) =>
|
|
16
|
+
if (x.isDigit) (n * 10 + x.asDigit, xs)
|
|
17
|
+
else if (n == 0) (0, x +: xs)
|
|
18
|
+
else (0, Seq.fill(n)(x) ++ xs)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
val result = str.foldLeft((0, Seq.empty[Char]))(nextChar)
|
|
22
|
+
result._2.reverse mkString
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
private def splitByEquals[T](xs: Seq[T]): Seq[Seq[T]] =
|
|
26
|
+
xs match {
|
|
27
|
+
case Seq() => Seq()
|
|
28
|
+
case x +: xss =>
|
|
29
|
+
val fs = xs takeWhile (_ == x)
|
|
30
|
+
fs +: splitByEquals(xs drop fs.length)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import org.scalatest.FunSuite
|
|
2
|
+
import org.scalatest.Matchers
|
|
3
|
+
|
|
4
|
+
class RunLengthEncodingTests extends FunSuite with Matchers {
|
|
5
|
+
|
|
6
|
+
test("encode empty string") {
|
|
7
|
+
RunLengthEncoding.encode("") should be ("")
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
test("encode single characters only") {
|
|
11
|
+
pending
|
|
12
|
+
RunLengthEncoding.encode("XYZ") should be ("XYZ")
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
test("decode empty string") {
|
|
16
|
+
pending
|
|
17
|
+
RunLengthEncoding.decode("") should be ("")
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
test("decode single characters only") {
|
|
21
|
+
pending
|
|
22
|
+
RunLengthEncoding.decode("XYZ") should be ("XYZ")
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
test("encode simple") {
|
|
26
|
+
pending
|
|
27
|
+
RunLengthEncoding.encode("AABBBCCCC") should be ("2A3B4C")
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
test("decode simple") {
|
|
31
|
+
pending
|
|
32
|
+
RunLengthEncoding.decode("2A3B4C") should be ("AABBBCCCC")
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
test("encode with single values") {
|
|
36
|
+
pending
|
|
37
|
+
RunLengthEncoding.encode("WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB") should
|
|
38
|
+
be ("12WB12W3B24WB")
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
test("decode with single values") {
|
|
42
|
+
pending
|
|
43
|
+
RunLengthEncoding.decode("12WB12W3B24WB") should be ("WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB")
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
test("decode(encode(...)) combination") {
|
|
47
|
+
pending
|
|
48
|
+
RunLengthEncoding.decode(
|
|
49
|
+
RunLengthEncoding.encode("zzz ZZ zZ")) should be ("zzz ZZ zZ")
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
}
|
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.0.6.
|
|
4
|
+
version: 2.0.6.4
|
|
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-01-
|
|
11
|
+
date: 2017-01-06 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rubyzip
|
|
@@ -5305,6 +5305,9 @@ files:
|
|
|
5305
5305
|
- tracks/perl6/exercises/allergies/cases.json
|
|
5306
5306
|
- tracks/perl6/exercises/anagram/Example.pm
|
|
5307
5307
|
- tracks/perl6/exercises/anagram/anagram.t
|
|
5308
|
+
- tracks/perl6/exercises/atbash-cipher/Example.p6
|
|
5309
|
+
- tracks/perl6/exercises/atbash-cipher/cases.json
|
|
5310
|
+
- tracks/perl6/exercises/atbash-cipher/cipher.t
|
|
5308
5311
|
- tracks/perl6/exercises/binary/Example.pm
|
|
5309
5312
|
- tracks/perl6/exercises/binary/binary.t
|
|
5310
5313
|
- tracks/perl6/exercises/bob/Example.pm
|
|
@@ -6765,6 +6768,10 @@ files:
|
|
|
6765
6768
|
- tracks/scala/exercises/roman-numerals/example.scala
|
|
6766
6769
|
- tracks/scala/exercises/roman-numerals/src/main/scala/.keep
|
|
6767
6770
|
- tracks/scala/exercises/roman-numerals/src/test/scala/RomanNumeralsTest.scala
|
|
6771
|
+
- tracks/scala/exercises/run-length-encoding/build.sbt
|
|
6772
|
+
- tracks/scala/exercises/run-length-encoding/example.scala
|
|
6773
|
+
- tracks/scala/exercises/run-length-encoding/src/main/scala/RunLengthEncoding.scala
|
|
6774
|
+
- tracks/scala/exercises/run-length-encoding/src/test/scala/RunLengthEncodingTests.scala
|
|
6768
6775
|
- tracks/scala/exercises/saddle-points/build.sbt
|
|
6769
6776
|
- tracks/scala/exercises/saddle-points/example.scala
|
|
6770
6777
|
- tracks/scala/exercises/saddle-points/src/main/scala/.keep
|