-
Notifications
You must be signed in to change notification settings - Fork 0
/
Day17.kt
93 lines (74 loc) · 3.15 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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package tr.emreone.adventofcode.days
import tr.emreone.kotlin_utils.automation.Day
import tr.emreone.kotlin_utils.data_structures.Dijkstra
import tr.emreone.kotlin_utils.data_structures.Graph
import tr.emreone.kotlin_utils.extensions.area
import tr.emreone.kotlin_utils.extensions.formatted
import tr.emreone.kotlin_utils.math.*
class Day17 : Day(17, 2023, "Clumsy Crucible") {
val heatMap = inputAsGrid.map { it.map { it.digitToInt() } }
val area = heatMap.area
data class State(
val pos: Point,
val movedStraight: Int,
val dir: Direction4?,
)
override fun part1(): Int {
val graph = object : Graph<State> {
override fun neighborsOf(node: State): Collection<State> {
return Direction4.all
.map { d ->
State(
node.pos + d,
movedStraight = if (d == node.dir) node.movedStraight + 1 else 1,
dir = d
)
}
.filter {
it.pos in area
&& it.movedStraight <= 3
&& it.dir != node.dir?.opposite
}
}
override fun cost(from: State, to: State): Int =
heatMap[to.pos.y][to.pos.x]
}
val start = State(origin, 0, null)
val x = Dijkstra(start, graph::neighborsOf, graph::cost).search { it.pos == area.lowerRight }
val path = x.path
heatMap.formatted { pos, v ->
if (pos in path.map { it.pos })
path.first { it.pos == pos }.movedStraight.toString()
else "."
}
return path.drop(1).sumOf { heatMap[it.pos.y][it.pos.x] }
}
override fun part2(): Int {
val graph = object : Graph<State> {
override fun neighborsOf(node: State): Collection<State> {
return (if (node.movedStraight < 4 && node.pos != origin)
listOf(node.copy(node.pos + node.dir!!, movedStraight = node.movedStraight + 1))
else Direction4.all.map { d ->
State(
node.pos + d,
movedStraight = if (d == node.dir) node.movedStraight + 1 else 1,
dir = d
)
}).filter { it.pos in area && it.movedStraight <= 10 && it.dir != node.dir?.opposite }
}
override fun cost(from: State, to: State): Int =
heatMap[to.pos.y][to.pos.x]
override fun costEstimation(from: State, to: State): Int =
from.pos manhattanDistanceTo to.pos
}
val start = State(origin, 0, null)
val x = Dijkstra(start, graph::neighborsOf, graph::cost).search { it.pos == area.lowerRight && it.movedStraight >= 4 }
val path = x.path
heatMap.formatted { pos, v ->
if (pos in path.map { it.pos })
path.first { it.pos == pos }.movedStraight.toString()
else "."
}
return path.drop(1).sumOf { heatMap[it.pos.y][it.pos.x] }
}
}