Skip to content

Commit 0242180

Browse files
committed
Optimizing Ram Run algorithm.
1 parent 1c1ec5e commit 0242180

File tree

3 files changed

+57
-9
lines changed

3 files changed

+57
-9
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,6 @@ Here are the solutions I have implemented along with the time it took to run eac
3737
| [Day 15: Warehouse Woes](src/test/kotlin/adventofcode/Day15Test.kt) | 129 |
3838
| [Day 16: Reindeer Maze](src/test/kotlin/adventofcode/Day16Test.kt) | 261 |
3939
| [Day 17: Chronospatial Computer](src/test/kotlin/adventofcode/Day17Test.kt) | 93 |
40-
| [Day 18: RAM Run](src/test/kotlin/adventofcode/Day18Test.kt) | 2,608 |
40+
| [Day 18: RAM Run](src/test/kotlin/adventofcode/Day18Test.kt) | 476 |
4141
| [Day 19: Linen Layout](src/test/kotlin/adventofcode/Day19Test.kt) | 60 |
4242
| [Day 20: Race Condition](src/test/kotlin/adventofcode/Day20Test.kt) | 0 |

src/main/kotlin/adventofcode/day18/RamRun.kt

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,27 @@ fun String.parsePoints(): List<Point2D> = lines()
2727
fun List<Point2D>.generateMap() = TextGrid(List(maxOf { it.y } + 1) { ".".repeat(maxOf { it.x } + 1) })
2828

2929
fun String.findFirstByteThatBlocksExit(): Point2D {
30-
val points = parsePoints()
30+
val bytes = parsePoints()
31+
val xRange = 0..bytes.maxOf { it.x }
32+
val yRange = 0..bytes.maxOf { it.y }
3133

3234
val start = Point2D.origin()
33-
val xRange = 0..points.maxOf { it.x }
34-
val yRange = 0..points.maxOf { it.y }
3535
val end = Point2D(xRange.last, yRange.last)
36-
val fallen = mutableSetOf<Point2D>()
36+
val fallenBytes = mutableSetOf<Point2D>()
3737
val neighbors =
38-
{ p: Point2D -> p.neighbors().filter { it.x in xRange && it.y in yRange }.filter { it !in fallen } }
39-
return points.first { p ->
40-
fallen.add(p)
41-
Graphs.bfs(start, end, neighbors).isEmpty()
38+
{ p: Point2D -> p.neighbors().filter { it.x in xRange && it.y in yRange }.filter { it !in fallenBytes } }
39+
var shortestPath = Graphs.shortestPaths(start, neighbors).pathTo(end).toSet()
40+
for(byte in bytes) {
41+
fallenBytes.add(byte)
42+
if(shortestPath.contains(byte)) {
43+
val shortestPaths = Graphs.shortestPaths(start, neighbors)
44+
if(!shortestPaths.pathExists(end)) {
45+
return byte
46+
}
47+
shortestPath = shortestPaths.pathTo(end).toSet()
48+
}
4249
}
50+
throw IllegalStateException("No byte blocks the exit")
4351
}
4452

4553
fun String.findShortestPathToExitAfter(nBytes: Int): Int {

src/main/kotlin/adventofcode/util/graph/Graphs.kt

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,46 @@ object Graphs {
7777
}
7878
}
7979

80+
/**
81+
* Implementation of Dijkstra's Algorithm
82+
* @param start the starting vertex
83+
* @param vertices the set of all vertices
84+
* @param neighbors a function that returns the neighbors of a vertex
85+
* @param weight a function that returns the weight of an edge
86+
* @return the shortest paths from the start vertex to all other vertices
87+
*/
88+
fun <V> shortestPaths(
89+
start: V,
90+
neighbors: (V) -> List<V>,
91+
weight: (V, V) -> Double = { _, _ -> 1.0 }
92+
): ShortestPaths<V> {
93+
val pred = mutableMapOf<V, V>()
94+
val dist = mutableMapOf<V, Double>()
95+
val visited = mutableSetOf<V>()
96+
dist[start] = 0.0
97+
val queue = PriorityQueue { l: V, r: V ->
98+
compareDoubles(
99+
dist.getOrDefault(l, Double.MAX_VALUE),
100+
dist.getOrDefault(r, Double.MAX_VALUE)
101+
)
102+
}
103+
queue.add(start)
104+
while (queue.isNotEmpty()) {
105+
val vertex = queue.poll()
106+
visited.add(vertex)
107+
val distanceToVertex = dist.getOrDefault(vertex, Double.MAX_VALUE)
108+
neighbors(vertex).filter { it !in visited }.forEach { neighbor ->
109+
val distanceThroughVertex = distanceToVertex + weight(vertex, neighbor)
110+
if (distanceThroughVertex < dist.getOrDefault(neighbor, Double.MAX_VALUE)) {
111+
pred[neighbor] = vertex
112+
dist[neighbor] = distanceThroughVertex
113+
queue.add(neighbor)
114+
}
115+
}
116+
}
117+
return ShortestPaths(start, dist, pred)
118+
}
119+
80120
/**
81121
* Implementation of Dijkstra's Algorithm
82122
* @param start the starting vertex

0 commit comments

Comments
 (0)