-
Notifications
You must be signed in to change notification settings - Fork 0
/
Day8.kt
41 lines (35 loc) · 1.46 KB
/
Day8.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package com.github.ephemient.aoc2023
import kotlinx.coroutines.flow.channelFlow
import kotlinx.coroutines.flow.fold
import kotlinx.coroutines.launch
class Day8(input: String) {
private val instructions = INSTRUCTIONS.matchAt(input, 0)!!.value
private val table = NODE.findAll(input).associateBy(
keySelector = { it.groupValues[1] },
valueTransform = { it.groupValues[2] to it.groupValues[3] }
)
private fun step(start: String) = instructions.fold(start) { acc, char ->
when (char) {
'L' -> table[acc]!!.first
'R' -> table[acc]!!.second
else ->
@Suppress("ThrowingExceptionsWithoutMessageOrCause", "UseCheckOrError")
throw IllegalStateException()
}
}
fun part1(): Int = instructions.length * generateSequence("AAA", ::step).indexOf("ZZZ")
suspend fun part2(): Long = instructions.length * channelFlow {
for (start in table.keys) {
if (!start.endsWith('A')) continue
launch {
val (index, end) = generateSequence(start, ::step).withIndex().first { (_, end) -> end.endsWith('Z') }
check(step(start) == step(end)) { "required for lcm solution" }
send(index)
}
}
}.fold(1L) { x, y -> lcm(x, y.toLong()) }
companion object {
private val INSTRUCTIONS = """[LR]+""".toRegex()
private val NODE = """(\w+) = \((\w+), (\w+)\)""".toRegex()
}
}