Skip to content

Commit 6d4d080

Browse files
committed
Solved day17 part 1
1 parent 3a3360e commit 6d4d080

File tree

5 files changed

+173
-2
lines changed

5 files changed

+173
-2
lines changed

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ plugins {
44

55
// project meta data
66
group 'de.havox_design.aoc2023'
7-
version '0.16.1'
7+
version '0.16.2'
88

99
// Switch to gradle "all" distribution.
1010
wrapper {
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package de.havox_design.aoc2023.day17
2+
3+
import kotlin.math.abs
4+
5+
data class Coordinate(val x: Int, val y: Int) : Comparable<Coordinate> {
6+
override fun compareTo(other: Coordinate): Int =
7+
when (val result = y.compareTo(other.y)) {
8+
0 -> x.compareTo(other.x)
9+
else -> result
10+
}
11+
12+
operator fun minus(other: Coordinate): Coordinate =
13+
Coordinate(x - other.x, y - other.y)
14+
15+
operator fun plus(other: Coordinate): Coordinate =
16+
Coordinate(x + other.x, y + other.y)
17+
18+
operator fun plus(i: Number): Coordinate =
19+
plus(Coordinate(i.toInt(), i.toInt()))
20+
21+
operator fun times(i: Number): Coordinate =
22+
this * Coordinate(i.toInt(), i.toInt())
23+
24+
operator fun times(other: Coordinate): Coordinate =
25+
Coordinate(x * other.x, y * other.y)
26+
27+
operator fun div(other: Coordinate): Coordinate =
28+
Coordinate(x / other.x, y / other.y)
29+
}
30+
31+
fun manhattanDistance(a: Coordinate, b: Coordinate) =
32+
abs(a.x - b.x) + abs(a.y - b.y)
33+
34+
val origin = Coordinate(0, 0)
35+
36+
fun <V> Map<Coordinate, V>.yRange() =
37+
keys.minByOrNull { it.y }!!.y to keys.maxByOrNull { it.y }!!.y
38+
39+
fun <V> Map<Coordinate, V>.xRange() =
40+
keys.minByOrNull { it.x }!!.x to keys.maxByOrNull { it.x }!!.x
41+
Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,77 @@
11
package de.havox_design.aoc2023.day17
22

3+
import java.util.*
4+
import kotlin.Comparator
5+
36
class Day17(private var filename: String) {
47
fun solvePart1(): Long =
5-
102L
8+
parseCoodinateMap()
9+
.findPath()
610

711
fun solvePart2(): Long =
812
0L
913

14+
private fun Map<Coordinate, Int>.findPath(
15+
maxConsecutive: Int = 3, minConsecutive: Int = 0, minMovedForEnd: Int = 0
16+
): Long {
17+
val xRange = xRange()
18+
.let { (a, b) -> a..b }
19+
val yRange = yRange()
20+
.let { (a, b) -> a..b }
21+
val target = Coordinate(xRange.last, yRange.last)
22+
val queue = priorityQueueOf(
23+
Comparator.comparing { -manhattanDistance(it.first.location, target) },
24+
History(FourDirectionFlipped.RIGHT, origin, 0) to 0L
25+
)
26+
val visited = mutableMapOf<History, Long>()
27+
var min = Long.MAX_VALUE
28+
29+
while (queue.isNotEmpty()) {
30+
val (history, loss) = queue.poll()
31+
32+
when {
33+
loss > (visited[history] ?: Long.MAX_VALUE) -> continue
34+
}
35+
when {
36+
history.location == target && history.count >= minMovedForEnd -> {
37+
min = min.coerceAtMost(loss)
38+
continue
39+
}
40+
}
41+
42+
history
43+
.moveDirections(maxConsecutive, minConsecutive)
44+
.asSequence()
45+
.filter { it.location.x in xRange && it.location.y in yRange }
46+
.map { it to loss + get(it.location)!! }
47+
.filter { it.second < (visited[it.first] ?: Long.MAX_VALUE) }
48+
.onEach { visited[it.first] = it.second }
49+
.toCollection(queue)
50+
}
51+
52+
return min
53+
54+
}
55+
56+
fun <T> priorityQueueOf(comparator: Comparator<T>, vararg args: T): PriorityQueue<T> {
57+
val queue = PriorityQueue<T>(comparator)
58+
queue.addAll(args)
59+
60+
return queue
61+
}
62+
63+
private fun parseCoodinateMap(): Map<Coordinate, Int> =
64+
getResourceAsText(filename)
65+
.flatMapIndexed { rowNumber, row ->
66+
row.mapIndexed { columnNumber, char ->
67+
Coordinate(columnNumber, rowNumber) to char.toIntValue()
68+
}
69+
}
70+
.toMap()
71+
1072
private fun getResourceAsText(path: String): List<String> =
1173
this.javaClass.classLoader.getResourceAsStream(path)!!.bufferedReader().readLines()
74+
75+
private fun Char.toIntValue() =
76+
code - '0'.code
1277
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package de.havox_design.aoc2023.day17
2+
3+
enum class FourDirectionFlipped(private val direction: Coordinate) {
4+
DOWN(Coordinate(0, 1)),
5+
UP(Coordinate(0, -1)),
6+
LEFT(Coordinate(-1, 0)),
7+
RIGHT(Coordinate(1, 0));
8+
9+
operator fun plus(other: Coordinate) =
10+
direction + other
11+
12+
fun turnLeft() = when (this) {
13+
UP -> LEFT
14+
LEFT -> DOWN
15+
DOWN -> RIGHT
16+
RIGHT -> UP
17+
}
18+
19+
fun turnRight() = when (this) {
20+
UP -> RIGHT
21+
RIGHT -> DOWN
22+
DOWN -> LEFT
23+
LEFT -> UP
24+
}
25+
26+
fun turnAround() = when (this) {
27+
UP -> DOWN
28+
DOWN -> UP
29+
LEFT -> RIGHT
30+
RIGHT -> LEFT
31+
}
32+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package de.havox_design.aoc2023.day17
2+
3+
data class History(
4+
val lastDirection: FourDirectionFlipped, val location: Coordinate, val count: Int
5+
) {
6+
@SuppressWarnings("kotlin:S6510")
7+
fun moveDirections(maxConsecutive: Int, minConsecutive: Int): List<History> {
8+
when (count) {
9+
0 -> {
10+
return listOf(FourDirectionFlipped.RIGHT, FourDirectionFlipped.DOWN)
11+
.map { History(it, it + location, 1) }
12+
}
13+
else -> {
14+
val leftRight =
15+
listOf(lastDirection.turnLeft(), lastDirection.turnRight())
16+
.map { History(it, it + location, 1) }
17+
val forward = History(lastDirection, lastDirection + location, count + 1)
18+
19+
return when {
20+
count < minConsecutive -> {
21+
listOf(forward)
22+
}
23+
24+
count == maxConsecutive -> {
25+
leftRight
26+
}
27+
28+
else -> leftRight + forward
29+
}
30+
}
31+
}
32+
}
33+
}

0 commit comments

Comments
 (0)