From cfdd6bcde4c984fdb5496f13c14c7d9162599981 Mon Sep 17 00:00:00 2001 From: Sven Weidauer Date: Wed, 25 Dec 2024 11:16:34 +0100 Subject: [PATCH] Day 16 part 1 --- 2024/src/main/kotlin/day16.kt | 63 ++++++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/2024/src/main/kotlin/day16.kt b/2024/src/main/kotlin/day16.kt index f1eafa9..fb5ca65 100644 --- a/2024/src/main/kotlin/day16.kt +++ b/2024/src/main/kotlin/day16.kt @@ -1,3 +1,64 @@ -fun main() { +import java.util.PriorityQueue +data class Position(val coordinate: Grid.Coordinate, val direction: Direction) + +fun main() { + val grid = CharGrid.read("day16.txt") + val start = grid.find('S')!! + val goal = grid.find('E')!! + + val startPosition = Position(start, Direction.East) + + val part1 = dijkstra(startPosition, goal = { it.coordinate == goal }) { current -> + Direction.entries + .asSequence() + .map { Position(current.coordinate.step(it), it) } + .filter { grid[it.coordinate] != '#' } + .map { it to 1 + current.direction.turns(it.direction) * 1000 } + } + println("Part 1: $part1") +} + +fun Direction.turns(to: Direction): Int = when { + this == to -> 0 + this == Direction.North && (to == Direction.East || to == Direction.West) -> 1 + this == Direction.North && to == Direction.South -> 2 + this == Direction.East && (to == Direction.North || to == Direction.South) -> 1 + this == Direction.East && to == Direction.West -> 2 + this == Direction.South && (to == Direction.West || to == Direction.East) -> 1 + this == Direction.South && to == Direction.North -> 2 + this == Direction.West && (to == Direction.North || to == Direction.South) -> 1 + this == Direction.West && to == Direction.East -> 2 + else -> error("Missing directions") +} + +fun dijkstra(start: T, goal: (T) -> Boolean, neighbors: (T) -> Sequence>): Int? { + val distanceFromStart = mutableMapOf(start to 0) + val visited = mutableSetOf() + val queue = PriorityQueue> { a, b -> a.second.compareTo(b.second) } + + queue.add(start to 0) + + while (true) { + val (current, totalDistance) = queue.poll() ?: break + if (goal(current)) { + return totalDistance + } + + visited.add(start) + + for ((neighbor, distance) in neighbors(current)) { + if (neighbor in visited) continue; + + val newDistance = totalDistance + distance + + val currentDistance = distanceFromStart[neighbor] + if (currentDistance == null || newDistance < currentDistance) { + distanceFromStart[neighbor] = newDistance + queue.add(neighbor to newDistance) + } + } + } + + return null } \ No newline at end of file