Advent of Code 2023 day 17
12/17/2023, 5:00 AMNeil Banman
12/17/2023, 6:08 AMNeil Banman
12/17/2023, 6:27 AMMarcin Wisniowski
12/17/2023, 6:36 AMPaul Woitaschek
12/17/2023, 7:47 AMephemient
12/17/2023, 7:49 AM(or even before it can stop at the end)but it cleaned up fine. adding a heuristic for A* saved such a tiny amount of time that it probably wasn't worthwhile.
knthmn
12/17/2023, 8:05 AMelizarov
12/17/2023, 8:45 AMephemient
12/17/2023, 9:34 AMPaul Woitaschek
12/17/2023, 10:31 AMCharles Flynn
12/17/2023, 10:34 AMMichael de Kaste
12/17/2023, 11:00 AMManuel Casariego
12/17/2023, 11:06 AMMichael de Kaste
12/17/2023, 11:10 AMif(nextPoint == endPoint && forwardCount >= minimalForward){
return nextScore
}
reaching the endpoint before you've done your minimum steps forward doesn't allow you to stop or something?ephemient
12/17/2023, 11:18 AMManuel Casariego
12/17/2023, 11:20 AMMichael de Kaste
12/17/2023, 12:03 PMphldavies
12/17/2023, 12:07 PMdijkstra
helper came in handy today. Not entirely happy with the ~700ms solve time, but not sure I'll have time to improve it much today.phldavies
12/17/2023, 1:34 PMBenchmark Mode Cnt Score Error Units
BenchDay17.intArrayPart1 avgt 3 40.432 ยฑ 3.062 ms/op
BenchDay17.intArrayPart2 avgt 3 134.850 ยฑ 6.991 ms/op
BenchDay17.part1 avgt 3 176.998 ยฑ 78.220 ms/op
BenchDay17.part2 avgt 3 752.731 ยฑ 795.443 ms/op
~135ms for part 2 - I'll take it.phldavies
12/17/2023, 1:40 PMval bests = IntArray((size * first().size).shl(6)) { Int.MAX_VALUE }
fun Crucible.idx() = (y * size + x).shl(6) + speed.shl(2) + direction.ordinal
Swapped my map for an IntArray to track bests in dijkstra.ephemient
12/17/2023, 1:45 PMphldavies
12/17/2023, 1:47 PM[u32;1272384]
in rust ๐ephemient
12/17/2023, 1:49 PMphldavies
12/17/2023, 1:51 PMephemient
12/17/2023, 1:52 PMvec![0u32; 1272384]
. it's not so easy with []
though ๐phldavies
12/17/2023, 1:52 PMephemient
12/17/2023, 1:55 PMTomasz Linkowski
12/17/2023, 2:20 PMephemient
12/17/2023, 2:21 PMephemient
12/17/2023, 2:23 PMTomasz Linkowski
12/17/2023, 2:25 PMCharles Flynn
12/17/2023, 2:37 PMtodd.ginsberg
12/17/2023, 5:04 PMMax Thiele
12/17/2023, 5:35 PMMichael de Kaste
12/17/2023, 6:06 PMMax Thiele
12/17/2023, 6:50 PMSwapped my map for an IntArray to track bests in dijkstra.That's a neat trick, wouldn't have thought the overhead of a map is that high
phldavies
12/17/2023, 6:57 PMNeil Banman
12/17/2023, 6:58 PMadding a heuristic for A* saved such a tiny amount of time that it probably wasn't worthwhile.Just using manhattan distance for heuristic cuts my solve time in half for both parts.
phldavies
12/17/2023, 6:58 PMephemient
12/17/2023, 6:59 PMtodd.ginsberg
12/17/2023, 6:59 PMephemient
12/17/2023, 6:59 PMJakub Gwรณลบdลบ
12/17/2023, 7:03 PMephemient
12/17/2023, 7:06 PMTim
12/17/2023, 9:15 PMephemient
12/17/2023, 9:20 PMNeil Banman
12/17/2023, 9:21 PMtodd.ginsberg
12/17/2023, 9:22 PMTim
12/17/2023, 9:23 PMoverride fun isStraightPossible(sameDirCount: Int) = sameDirCount < 10
override fun isTurnPossible(sameDirCount: Int) = sameDirCount >= 4
override fun isEndPossible(sameDirCount: Int) = sameDirCount >= 4
And in debugging output I only see the original direction repeated if below four.Tim
12/17/2023, 9:24 PMtodd.ginsberg
12/17/2023, 9:24 PMTim
12/17/2023, 9:26 PMephemient
12/17/2023, 9:27 PMtodd.ginsberg
12/17/2023, 9:27 PMephemient
12/17/2023, 9:28 PMTim
12/17/2023, 9:29 PMEugen Martynov
12/19/2023, 9:20 AMEugen Martynov
12/19/2023, 9:20 AMPaul Woitaschek
12/19/2023, 9:28 AMBecause it is difficult to keep the top-heavy crucible going in a straight line for very long, it can move at most three blocks
Eugen Martynov
12/19/2023, 9:30 AMEugen Martynov
12/19/2023, 9:30 AMPaul Woitaschek
12/19/2023, 9:33 AM2>>34^>>>1323
32v>>>35v5623
This is the optimal path
2413432311323
3215453535623
Your way would be:
2>>3^>2311323
32v>>53535623
Paul Woitaschek
12/19/2023, 9:34 AMPaul Woitaschek
12/19/2023, 9:34 AM2>>3^>>>11323
32v>>53v35623
Eugen Martynov
12/19/2023, 9:34 AMEugen Martynov
12/19/2023, 9:38 AMEugen Martynov
12/19/2023, 9:39 AMPaul Woitaschek
12/19/2023, 9:39 AMPaul Woitaschek
12/19/2023, 9:40 AMEugen Martynov
12/19/2023, 9:48 AMEugen Martynov
12/19/2023, 9:48 AMEugen Martynov
12/19/2023, 9:48 AMEugen Martynov
12/19/2023, 10:02 AMEugen Martynov
12/19/2023, 10:03 AMEugen Martynov
12/19/2023, 10:04 AMEugen Martynov
12/19/2023, 10:04 AMPaul Woitaschek
12/19/2023, 10:05 AMEugen Martynov
12/19/2023, 10:05 AMEugen Martynov
12/19/2023, 10:05 AMEugen Martynov
12/19/2023, 10:05 AMOzioma Ogbe
12/21/2023, 2:30 PMimport java.util.PriorityQueue
val pointDistances = mutableMapOf<NodeState, Long>()
fun main() {
val lines = input.trim().split("\n")
val startPoint1 = NodeState(Point(0, 0), lines[0][0].digitToInt().toLong(), Direction.RIGHT, 0)
pointDistances[startPoint1] = startPoint1.value
val unvisitedPoints = PriorityQueue<NodeState>() { a, b ->
val thisD = pointDistances[a] ?: Long.MAX_VALUE
val otherD = pointDistances[b] ?: Long.MAX_VALUE
(thisD).compareTo(otherD)
}
val visitedPoints = mutableSetOf<NodeState>()
unvisitedPoints.add(startPoint1)
while (unvisitedPoints.isNotEmpty()) {
val nodeState = unvisitedPoints.poll()
val left = if (nodeState.steps >= 4) nodeState.point.turnLeft(nodeState.direction) else null
val right = if (nodeState.steps >= 4) nodeState.point.turnRight(nodeState.direction) else null
val forward = if (nodeState.steps < 10) nodeState.point.moveForward(nodeState.direction) else null
// val left = nodeState.point.turnLeft(nodeState.direction)
// val right = nodeState.point.turnRight(nodeState.direction)
// val forward = if (nodeState.steps < 3) nodeState.point.moveForward(nodeState.direction) else null
visitedPoints.add(nodeState)
listOfNotNull(
left, right, forward
).filter { it.second.x in lines.indices && it.second.y in lines[0].indices }.mapIndexed { index, value ->
NodeState(
value.second,
lines[value.second.x][value.second.y].digitToInt().toLong(),
value.first,
if (value == forward) nodeState.steps + 1 else 1
)
}.filter {
unvisitedPoints.contains(it) || !visitedPoints.contains(it)
}.forEach { node ->
if (node.point == Point(lines.lastIndex, lines[0].lastIndex)) {
println(pointDistances[nodeState]!! + node.value - startPoint1.value)
return
}
val currentDistance = pointDistances[nodeState] ?: Long.MAX_VALUE
if (currentDistance + node.value < (pointDistances[node]
?: Long.MAX_VALUE)
) {
pointDistances[node] = currentDistance + node.value
}
unvisitedPoints.remove(node)
unvisitedPoints.offer(node)
}
}
}
data class NodeState(val point: Point, val value: Long, val direction: Direction, val steps: Int)
elizarov
12/21/2023, 3:06 PMOzioma Ogbe
12/21/2023, 3:53 PMNeil Banman
12/21/2023, 4:17 PMkqr
12/30/2023, 8:52 PMelizarov
12/31/2023, 11:25 PMkqr
01/01/2024, 11:25 AMpq.add(initState)
visited.add(initState)
while(pq.notempty) {
....
if () {
pq.add(newState)
visited.add(newState)
}
}
vs
pq.add(initState)
while(pq.notempty) {
visited.add(state)
....
if () {
pq.add(newState)
}
}
why is it ok to put new state already to visited states even when we were not there yet?
is it guaranteed that later visit will always be same/worse?elizarov
01/01/2024, 1:02 PMkqr
01/01/2024, 4:24 PMelizarov
01/01/2024, 4:40 PMkqr
01/02/2024, 12:27 PMBecause the queue is ordered by heatLoss, so anything we say we've seen now will be the quickest we could have arrived at that state, even if the work is queued up to be evaluated later. So there's not real reason not to do it now.
and I didn't understand whyelizarov
01/02/2024, 6:47 PMkqr
01/02/2024, 7:58 PMNeil Banman
01/02/2024, 8:16 PMtodd.ginsberg
01/02/2024, 8:28 PMephemient
01/02/2024, 8:38 PM