Skip to content

Commit 0dff315

Browse files
committed
Add solution for Y2024D18.
1 parent f54483e commit 0dff315

File tree

7 files changed

+110
-2
lines changed

7 files changed

+110
-2
lines changed

Diff for: README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ _"Anything that's worth doing, is worth overdoing."_
1515
Table of contents to jump straight to the problem you're looking for.
1616

1717
<details open>
18-
<summary>2024 (34x⭐)</summary>
18+
<summary>2024 (36x⭐)</summary>
1919

2020
| Day | Title | Stars |
2121
|:---:|:------------------------------------------------------------|:-----:|
@@ -36,6 +36,7 @@ Table of contents to jump straight to the problem you're looking for.
3636
| 15 | [Warehouse Woes](solutions/aockt/y2024/Y2024D15.kt) | ⭐⭐ |
3737
| 16 | [Reindeer Maze](solutions/aockt/y2024/Y2024D16.kt) | ⭐⭐ |
3838
| 17 | [Chronospatial Computer](solutions/aockt/y2024/Y2024D17.kt) | ⭐⭐ |
39+
| 18 | [RAM Run](solutions/aockt/y2024/Y2024D18.kt) | ⭐⭐ |
3940

4041
</details>
4142

Diff for: inputs/aockt/y2024/d18/input.txt

19.3 KB
Binary file not shown.

Diff for: inputs/aockt/y2024/d18/solution_part1.txt

26 Bytes
Binary file not shown.

Diff for: inputs/aockt/y2024/d18/solution_part2.txt

27 Bytes
Binary file not shown.

Diff for: solutions/aockt/util/Search.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package aockt.util
33
import java.util.PriorityQueue
44

55
/** A type implementing this interface can represent a network of nodes usable for search algorithms. */
6-
interface Graph<T : Any> {
6+
fun interface Graph<T : Any> {
77

88
/** Returns all the possible nodes to visit starting from this [node] associated with the cost of travel. */
99
fun neighboursOf(node: T): Iterable<Pair<T, Int>>

Diff for: solutions/aockt/y2024/Y2024D18.kt

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package aockt.y2024
2+
3+
import aockt.util.*
4+
import aockt.util.spacial.*
5+
import io.github.jadarma.aockt.core.Solution
6+
7+
object Y2024D18 : Solution {
8+
9+
/**
10+
* Returns the minimum amount of steps needed to navigate the [area] from corner to corner, avoiding the
11+
* [corrupted] points, or -1 if it is impossible to do so.
12+
*/
13+
private fun stepsToEscape(area: Area, corrupted: Set<Point>): Int =
14+
Graph<Pair<Point, Direction>> { (point, direction) ->
15+
Direction.all
16+
.asSequence()
17+
.minus(direction.opposite)
18+
.map { point.move(it) to it }
19+
.filter { it.first in area }
20+
.filterNot { it.first in corrupted }
21+
.map { it to 1 }
22+
.asIterable()
23+
}.search(
24+
start = Point(0, 0) to Direction.Right,
25+
goalFunction = { it.first == Point(area.width - 1, area.height - 1) },
26+
).path()?.cost ?: -1
27+
28+
/**
29+
* Parse the [input] and return the surrounding [Area] and the list of [Point]s that will get corrupted.
30+
* If [partial], only returns some of the points from the actual input.
31+
* The area size and partial count is determined by the size of the input, to allow for running examples.
32+
*/
33+
private fun parseInput(input: String, partial: Boolean): Pair<Area, List<Point>> = parse {
34+
val points = input
35+
.lineSequence()
36+
.map { it.split(',', limit = 2).map(String::toInt) }
37+
.map { (x, y) -> Point(x, y) }
38+
.toList()
39+
40+
val size = if (points.size > 50) 71 else 7
41+
42+
val corruptedPoints = when (partial) {
43+
true -> if (size == 71) 1024 else 12
44+
else -> Int.MAX_VALUE
45+
}
46+
47+
Area(size, size) to points.take(corruptedPoints)
48+
}
49+
50+
override fun partOne(input: String): Int {
51+
val (area, points) = parseInput(input, partial = true)
52+
return stepsToEscape(area, points.toSet())
53+
}
54+
55+
override fun partTwo(input: String): String {
56+
val (area, points) = parseInput(input, partial = false)
57+
var blocker = Int.MAX_VALUE
58+
59+
points.indices.toList().binarySearch { index ->
60+
val corrupted = points.take(index + 1).toSet()
61+
val canEscape = stepsToEscape(area, corrupted) > -1
62+
63+
if (canEscape) -1 else 1.also { blocker = index }
64+
}
65+
66+
return with(points[blocker]) { "$x,$y" }
67+
}
68+
}

Diff for: tests/aockt/y2024/Y2024D18Test.kt

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package aockt.y2024
2+
3+
import io.github.jadarma.aockt.test.AdventDay
4+
import io.github.jadarma.aockt.test.AdventSpec
5+
6+
@AdventDay(2024, 18, "RAM Run")
7+
class Y2024D18Test : AdventSpec<Y2024D18>({
8+
9+
val exampleInput = """
10+
5,4
11+
4,2
12+
4,5
13+
3,0
14+
2,1
15+
6,3
16+
2,4
17+
1,5
18+
0,6
19+
3,3
20+
2,6
21+
5,1
22+
1,2
23+
5,5
24+
2,5
25+
6,5
26+
1,4
27+
0,4
28+
6,4
29+
1,1
30+
6,1
31+
1,0
32+
0,5
33+
1,6
34+
2,0
35+
""".trimIndent()
36+
37+
partOne { exampleInput shouldOutput 22 }
38+
partTwo { exampleInput shouldOutput "6,1" }
39+
})

0 commit comments

Comments
 (0)