Skip to content

Commit b3f4c62

Browse files
committed
2018-15, part 1: use Dijkstra's algorithm instead of A*
* Since minimal paths to all targets are calculated in a single call of that algorithm, it is much less memory hungry and much faster than multiple calls to the A* algorithm. * Most of the tests pass. But the "in reading order" precedence when choosing one of equally expensive vertices still is to implement. * Since we use a logger in production code, add logback classic dependency to the runtime classpath.
1 parent 98ea557 commit b3f4c62

File tree

3 files changed

+70
-11
lines changed

3 files changed

+70
-11
lines changed

build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ repositories {
1010
dependencies {
1111
implementation(libs.kotlin.logging)
1212
implementation(libs.kotlinx.coroutines.core)
13+
runtimeOnly(libs.logback.classic)
1314

1415
testImplementation(libs.kotest.assertions.table)
1516
testImplementation(libs.kotest.runner.junit5)

src/main/kotlin/de/ronny_h/aoc/year2018/day15/BeverageBandits.kt

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -85,16 +85,16 @@ class CombatArea(input: List<String>) : SimpleCharGrid(input) {
8585
return
8686
}
8787

88-
val targetsWithPaths = targets.flatMap { target ->
89-
target.position.neighbours()
90-
.filter { getAt(it) == cavern }
91-
.flatMap { inRange ->
92-
shortestPaths(position, inRange) { neighbour ->
93-
getAt(neighbour) == cavern
94-
}
95-
.map { Target(inRange, it) }
96-
}
88+
val targetsInRange = targets.flatMap { target ->
89+
target.position.neighbours().filter { getAt(it) == cavern }
9790
}
91+
// TODO make path precedence in reading order configurable
92+
val targetsWithPaths = shortestPaths(
93+
start = position,
94+
goals = targetsInRange,
95+
isObstacle = { it != cavern })
96+
.map { Target(it.path.last(), it) }
97+
9898
if (targetsWithPaths.isEmpty()) {
9999
// no path to any target found
100100
return

src/test/kotlin/de/ronny_h/aoc/year2018/day15/BeverageBanditsTest.kt

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package de.ronny_h.aoc.year2018.day15
22

33
import de.ronny_h.aoc.extensions.asList
44
import io.kotest.core.spec.style.StringSpec
5+
import io.kotest.data.forAll
6+
import io.kotest.data.row
57
import io.kotest.matchers.shouldBe
68

79
class BeverageBanditsTest : StringSpec({
@@ -122,8 +124,64 @@ class BeverageBanditsTest : StringSpec({
122124
combatArea.takeOneRound() shouldBe false
123125
}
124126

125-
"part 1: the outcome of the battle of the small example" {
126-
BeverageBandits().part1(input) shouldBe 27730
127+
"part 1: the outcome of the battle of some given examples" {
128+
val input2 = """
129+
#######
130+
#G..#E#
131+
#E#E.E#
132+
#G.##.#
133+
#...#E#
134+
#...E.#
135+
#######
136+
""".asList()
137+
val input3 = """
138+
#######
139+
#E..EG#
140+
#.#G.E#
141+
#E.##E#
142+
#G..#.#
143+
#..E#.#
144+
#######
145+
""".asList()
146+
val input4 = """
147+
#######
148+
#E.G#.#
149+
#.#G..#
150+
#G.#.G#
151+
#G..#.#
152+
#...E.#
153+
#######
154+
""".asList()
155+
val input5 = """
156+
#######
157+
#.E...#
158+
#.#..G#
159+
#.###.#
160+
#E#G#G#
161+
#...#G#
162+
#######
163+
""".asList()
164+
val input6 = """
165+
#########
166+
#G......#
167+
#.E.#...#
168+
#..##..G#
169+
#...##..#
170+
#...#...#
171+
#.G...G.#
172+
#.....G.#
173+
#########
174+
""".asList()
175+
forAll(
176+
row(input, 27730),
177+
row(input2, 36334),
178+
row(input3, 39514),
179+
row(input4, 27755),
180+
row(input5, 28944),
181+
row(input6, 18740),
182+
) { input, outcome ->
183+
BeverageBandits().part1(input) shouldBe outcome
184+
}
127185
}
128186

129187
"part 2" {

0 commit comments

Comments
 (0)