Skip to content

Commit 9c40ecc

Browse files
committed
Solution 2017-09 (Stream Processing)
1 parent c2cb23d commit 9c40ecc

File tree

2 files changed

+161
-0
lines changed

2 files changed

+161
-0
lines changed
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package de.ronny_h.aoc.year2017.day09
2+
3+
import de.ronny_h.aoc.AdventOfCode
4+
import de.ronny_h.aoc.year2017.day09.State.*
5+
6+
fun main() = StreamProcessing().run(16689, 7982)
7+
8+
class StreamProcessing : AdventOfCode<Int>(2017, 9) {
9+
override fun part1(input: List<String>): Int = input.single().parseGroups().score
10+
override fun part2(input: List<String>): Int = input.single().parseGroups().garbage
11+
}
12+
13+
enum class State {
14+
Start, End, InGroup, InGarbage, Canceled
15+
}
16+
17+
data class Groups(
18+
val count: Int,
19+
val score: Int,
20+
val garbage: Int,
21+
)
22+
23+
/*
24+
The state transitions are:
25+
--<--> --!-->
26+
S --{--> in-group in-garbage canceled
27+
E <--}-- <-->-- | | <--*--
28+
-*^!>-
29+
30+
in-group: { -> level++
31+
} -> level--
32+
*/
33+
fun String.parseGroups(): Groups {
34+
var state = Start
35+
var nestingLevel = 0
36+
var groupCount = 0
37+
var score = 0
38+
var garbage = 0
39+
40+
forEach { c ->
41+
when (state) {
42+
Start -> {
43+
state = when (c) {
44+
'{' -> {
45+
nestingLevel++
46+
InGroup
47+
}
48+
49+
else -> error("illegal character $c in state $state")
50+
}
51+
}
52+
53+
End -> error("illegal character $c in state $state")
54+
55+
InGroup -> {
56+
state = when (c) {
57+
',' -> InGroup
58+
'{' -> {
59+
nestingLevel++
60+
InGroup
61+
}
62+
63+
'}' -> {
64+
score += nestingLevel
65+
nestingLevel--
66+
groupCount++
67+
if (nestingLevel > 0) {
68+
InGroup
69+
} else {
70+
End
71+
}
72+
}
73+
74+
'<' -> InGarbage
75+
else -> error("illegal character $c in state $state")
76+
}
77+
}
78+
79+
InGarbage -> {
80+
state = when (c) {
81+
'>' -> InGroup
82+
'!' -> Canceled
83+
else -> {
84+
garbage++
85+
InGarbage
86+
}
87+
}
88+
}
89+
90+
Canceled -> {
91+
state = InGarbage
92+
}
93+
}
94+
}
95+
check(state == End) { "state should be End at the end, but was: $state" }
96+
check(nestingLevel == 0) { "nesting level should be 0 at the end, but was: $nestingLevel" }
97+
return Groups(groupCount, score, garbage)
98+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package de.ronny_h.aoc.year2017.day09
2+
3+
import io.kotest.core.spec.style.StringSpec
4+
import io.kotest.data.forAll
5+
import io.kotest.data.row
6+
import io.kotest.matchers.shouldBe
7+
8+
class StreamProcessingTest : StringSpec({
9+
10+
"the number of groups" {
11+
forAll(
12+
row("{}", 1),
13+
row("{{{}}}", 3),
14+
row("{{},{}}", 3),
15+
row("{{{},{},{{}}}}", 6),
16+
row("{<{},{},{{}}>}", 1),
17+
row("{<a>,<a>,<a>,<a>}", 1),
18+
row("{{<a>},{<a>},{<a>},{<a>}}", 5),
19+
row("{{<!>},{<!>},{<!>},{<a>}}", 2),
20+
) { input, numberOfGroups ->
21+
input.parseGroups().count shouldBe numberOfGroups
22+
}
23+
}
24+
25+
"the total score for all groups in the input" {
26+
forAll(
27+
row("{}", 1),
28+
row("{{{}}}", 6),
29+
row("{{},{}}", 5),
30+
row("{{{},{},{{}}}}", 16),
31+
row("{<a>,<a>,<a>,<a>}", 1),
32+
row("{{<ab>},{<ab>},{<ab>},{<ab>}}", 9),
33+
row("{{<!!>},{<!!>},{<!!>},{<!!>}}", 9),
34+
row("{{<a!>},{<a!>},{<a!>},{<ab>}}", 3),
35+
) { input, score ->
36+
input.parseGroups().score shouldBe score
37+
}
38+
}
39+
40+
"the number of non-canceled characters within the garbage" {
41+
forAll(
42+
row("{<>}", 0),
43+
row("{<random characters>}", 17),
44+
row("{<<<<>}", 3),
45+
row("{<{!>}>}", 2),
46+
row("{<!!>}", 0),
47+
row("{<!!!>>}", 0),
48+
row("{<{o\"i!a,<{i<a>}", 10),
49+
) { input, garbage ->
50+
input.parseGroups().garbage shouldBe garbage
51+
}
52+
}
53+
54+
"part 1: the total score for all groups in the input" {
55+
val input = listOf("{{<ab>},{<ab>},{<ab>},{<ab>}}")
56+
StreamProcessing().part1(input) shouldBe 9
57+
}
58+
59+
"part 2: the number of non-canceled characters within the garbage" {
60+
val input = listOf("{<{!>}>}")
61+
StreamProcessing().part2(input) shouldBe 2
62+
}
63+
})

0 commit comments

Comments
 (0)