Skip to content

Commit 1bf9317

Browse files
authored
Day 18 2024 (#281)
1 parent 4034eff commit 1bf9317

File tree

4 files changed

+126
-0
lines changed

4 files changed

+126
-0
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package me.peckb.aoc._2024.calendar.day18
2+
3+
import javax.inject.Inject
4+
import me.peckb.aoc.generators.InputGenerator.InputGeneratorFactory
5+
import me.peckb.aoc.pathing.GenericIntDijkstra
6+
7+
class Day18 @Inject constructor(
8+
private val generatorFactory: InputGeneratorFactory,
9+
) {
10+
fun partOne(filename: String) = generatorFactory.forFile(filename).readAs(::location) { locations ->
11+
val area = Array(HEIGHT) { Array(WIDTH) { Memory.EMPTY } }
12+
13+
locations.take(1024).forEach { (y, x) ->
14+
area[y][x] = Memory.CORRUPTED
15+
}
16+
17+
val solver = object : GenericIntDijkstra<Location>() { }
18+
19+
val solutions = solver.solve(
20+
Location(0, 0).withArea(area).withPreviousPath(emptyList()),
21+
Location(HEIGHT - 1, WIDTH- 1)
22+
)
23+
24+
solutions[Location(HEIGHT - 1, WIDTH- 1)]
25+
}
26+
27+
fun partTwo(filename: String) = generatorFactory.forFile(filename).readAs(::location) { locations ->
28+
val area = Array(HEIGHT) { Array(WIDTH) { Memory.EMPTY } }
29+
val start = Location(0, 0).withArea(area).withPreviousPath(emptyList())
30+
val end = Location(HEIGHT - 1, WIDTH - 1)
31+
32+
val locationList = locations.toList()
33+
34+
var counter = 1024
35+
locationList.take(1024).forEach { (y, x) -> area[y][x] = Memory.CORRUPTED }
36+
37+
var solutions: Map<Location, Int> = emptyMap()
38+
val solver = object : GenericIntDijkstra<Location>() {}
39+
search@ do {
40+
val next = locationList[counter++]
41+
area[next.y][next.x] = Memory.CORRUPTED
42+
43+
if (solutions.entries.firstOrNull { it.key == end }?.key?.path?.contains(next) == false) {
44+
continue@search
45+
}
46+
47+
solutions = solver.solve(start, end)
48+
} while(solutions[end] != null)
49+
50+
locationList[counter - 1].let { "${it.x},${it.y}" }
51+
}
52+
53+
private fun location(line: String) = line.split(",")
54+
.map { it.toInt() }
55+
.let { (x, y) -> Location(y, x) }
56+
57+
companion object {
58+
const val WIDTH = 71
59+
const val HEIGHT = 71
60+
}
61+
}
62+
63+
data class Location(val y: Int, val x: Int) : GenericIntDijkstra.DijkstraNode<Location> {
64+
lateinit var path: List<Location>
65+
lateinit var area: Array<Array<Memory>>
66+
67+
fun withArea(area: Array<Array<Memory>>) = apply { this.area = area }
68+
fun withPreviousPath(path: List<Location>) = apply { this.path = path.plus(this) }
69+
70+
override fun neighbors(): Map<Location, Int> {
71+
return Direction.entries.mapNotNull { d ->
72+
val (newY, newX) = d.yDelta + y to d.xDelta + x
73+
if (newY in area.indices && newX in area[newY].indices && area[newY][newX] == Memory.EMPTY) {
74+
Location(newY, newX).withArea(area).withPreviousPath(path)
75+
} else { null }
76+
}.associateWith { 1 }
77+
}
78+
}
79+
80+
enum class Direction(val yDelta: Int, val xDelta: Int) {
81+
N(-1, 0),
82+
E(0, 1),
83+
S(1, 0),
84+
W(0, -1);
85+
}
86+
87+
enum class Memory(val s: String) {
88+
EMPTY("."), CORRUPTED("#");
89+
90+
override fun toString(): String = s
91+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
## [Day 18: RAM Run](https://adventofcode.com/2024/day/18)

src/test/kotlin/me/peckb/aoc/_2024/TestDayComponent.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import me.peckb.aoc._2024.calendar.day14.Day14Test
1717
import me.peckb.aoc._2024.calendar.day15.Day15Test
1818
import me.peckb.aoc._2024.calendar.day16.Day16Test
1919
import me.peckb.aoc._2024.calendar.day17.Day17Test
20+
import me.peckb.aoc._2024.calendar.day18.Day18Test
2021
import javax.inject.Singleton
2122
import me.peckb.aoc.DayComponent
2223
import me.peckb.aoc.InputModule
@@ -42,4 +43,5 @@ internal interface TestDayComponent : DayComponent {
4243
fun inject(day15Test: Day15Test)
4344
fun inject(day16Test: Day16Test)
4445
fun inject(day17Test: Day17Test)
46+
fun inject(day18Test: Day18Test)
4547
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package me.peckb.aoc._2024.calendar.day18
2+
3+
import javax.inject.Inject
4+
5+
import me.peckb.aoc._2024.DaggerTestDayComponent
6+
import org.junit.jupiter.api.Assertions.assertEquals
7+
import org.junit.jupiter.api.BeforeEach
8+
import org.junit.jupiter.api.Test
9+
10+
internal class Day18Test {
11+
@Inject
12+
lateinit var day18: Day18
13+
14+
@BeforeEach
15+
fun setup() {
16+
DaggerTestDayComponent.create().inject(this)
17+
}
18+
19+
@Test
20+
fun testDay18PartOne() {
21+
assertEquals(416, day18.partOne(DAY_18))
22+
}
23+
24+
@Test
25+
fun testDay18PartTwo() {
26+
assertEquals("50,23", day18.partTwo(DAY_18))
27+
}
28+
29+
companion object {
30+
private const val DAY_18: String = "advent-of-code-input/2024/day18.input"
31+
}
32+
}

0 commit comments

Comments
 (0)