Skip to content

Commit 4b39829

Browse files
authored
Merge pull request #263 from abo64/exercise-run-length-encoding
new exercise run-length-encoding
2 parents a754e8e + d7fc210 commit 4b39829

File tree

5 files changed

+102
-0
lines changed

5 files changed

+102
-0
lines changed

config.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,15 @@
2828
"Sets"
2929
]
3030
},
31+
{
32+
"slug": "run-length-encoding",
33+
"difficulty": 1,
34+
"topics": [
35+
"Algorithms",
36+
"Transforming",
37+
"Strings"
38+
]
39+
},
3140
{
3241
"slug": "hamming",
3342
"difficulty": 2,
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
scalaVersion := "2.12.1"
2+
3+
libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.1" % "test"
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
object RunLengthEncoding {
2+
3+
def encode(str: String): String = ???
4+
5+
def decode(str: String): String = ???
6+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
}

0 commit comments

Comments
 (0)