-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay17.kt
58 lines (50 loc) · 1.54 KB
/
Day17.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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import kotlin.math.absoluteValue
import kotlin.math.sign
object Day17 : AdventDay() {
override fun solve() {
val data = reads<String>()?.singleOrNull() ?: return
val targetArea = data.toTargetArea()
val maxX = targetArea.x.maxOf { it.absoluteValue }
val maxY = targetArea.y.maxOf { it.absoluteValue }
targetArea.runSimulations(x = -maxX..maxX, y = -maxY..maxY).run {
maxOf { state -> state.yHistory.maxOf { it } }.printIt()
size.printIt()
}
}
}
private fun String.toTargetArea() = removePrefix("target area: x=").split(", y=")
.map { rng -> rng.split("..").let { (from, to) -> from.toInt() directedTo to.toInt() } }
.let { (x, y) -> TargetArea(x, y) }
private data class TargetArea(val x: IntProgression, val y: IntProgression) {
fun runSimulations(x: IntRange, y: IntRange): List<State> {
return buildList {
for (vx in x) for (vy in y) simulate(vx, vy)?.let { add(it) }
}
}
fun simulate(vx: Int, vy: Int): State? {
var state = State(vx, vy)
while (state.canReach(this)) {
state = state.step()
if (state.x in x && state.y in y) return state
}
return null
}
}
private data class State(
val vx: Int, val vy: Int,
val x: Int = 0, val y: Int = 0,
val yHistory: List<Int> = listOf(),
) {
fun step() = State(
x = x + vx,
y = y + vy,
vx = vx - vx.sign,
vy = vy - 1,
yHistory = yHistory + y,
)
fun canReach(targetArea: TargetArea) = when {
vy < 0 && y < targetArea.y.first -> false
vx == 0 && x !in targetArea.x -> false
else -> true
}
}