Day 15
This commit is contained in:
50
src/main/kotlin/com/basdado/adventofcode/AllDays.kt
Normal file
50
src/main/kotlin/com/basdado/adventofcode/AllDays.kt
Normal file
@@ -0,0 +1,50 @@
|
||||
package com.basdado.adventofcode
|
||||
|
||||
import com.basdado.adventofcode.day1.Day1
|
||||
import com.basdado.adventofcode.day10.Day10
|
||||
import com.basdado.adventofcode.day11.Day11
|
||||
import com.basdado.adventofcode.day12.Day12
|
||||
import com.basdado.adventofcode.day13.Day13
|
||||
import com.basdado.adventofcode.day14.Day14
|
||||
import com.basdado.adventofcode.day15.Day15
|
||||
import com.basdado.adventofcode.day2.Day2
|
||||
import com.basdado.adventofcode.day3.Day3
|
||||
import com.basdado.adventofcode.day4.Day4
|
||||
import com.basdado.adventofcode.day5.Day5
|
||||
import com.basdado.adventofcode.day6.Day6
|
||||
import com.basdado.adventofcode.day7.Day7
|
||||
import com.basdado.adventofcode.day8.Day8
|
||||
import com.basdado.adventofcode.day9.Day9
|
||||
|
||||
fun main() {
|
||||
Day1.puzzle1()
|
||||
Day1.puzzle2()
|
||||
Day2.puzzle1()
|
||||
Day2.puzzle2()
|
||||
Day3.puzzle1()
|
||||
Day3.puzzle2()
|
||||
Day4.puzzle1()
|
||||
Day4.puzzle2()
|
||||
Day5.puzzle1()
|
||||
Day5.puzzle2()
|
||||
Day6.puzzle1()
|
||||
Day6.puzzle2()
|
||||
Day7.puzzle1()
|
||||
Day7.puzzle2()
|
||||
Day8.puzzle1()
|
||||
Day8.puzzle2()
|
||||
Day9.puzzle1()
|
||||
Day9.puzzle2()
|
||||
Day10.puzzle1()
|
||||
Day10.puzzle2()
|
||||
Day11.puzzle1()
|
||||
Day11.puzzle2()
|
||||
Day12.puzzle1()
|
||||
Day12.puzzle2()
|
||||
Day13.puzzle1()
|
||||
Day13.puzzle2()
|
||||
Day14.puzzle1()
|
||||
Day14.puzzle2()
|
||||
Day15.puzzle1()
|
||||
Day15.puzzle2()
|
||||
}
|
||||
160
src/main/kotlin/com/basdado/adventofcode/day15/Day15.kt
Normal file
160
src/main/kotlin/com/basdado/adventofcode/day15/Day15.kt
Normal file
@@ -0,0 +1,160 @@
|
||||
package com.basdado.adventofcode.day15
|
||||
|
||||
import com.basdado.adventofcode.IntCodeProgram
|
||||
import com.basdado.adventofcode.StackBasedInputProvider
|
||||
import com.basdado.adventofcode.day11.Day11
|
||||
import com.basdado.adventofcode.loadProgramData
|
||||
|
||||
const val DAY15_INPUT_PATH = "/day/15/input.txt"
|
||||
|
||||
fun main() {
|
||||
Day15.puzzle1()
|
||||
Day15.puzzle2()
|
||||
}
|
||||
|
||||
object Day15 {
|
||||
|
||||
val movementDirections = mapOf(
|
||||
// North
|
||||
Pair(1L, Vector2i(0, 1)),
|
||||
// South
|
||||
Pair(2L, Vector2i(0, -1)),
|
||||
// West
|
||||
Pair(3L, Vector2i(-1, 0)),
|
||||
// East
|
||||
Pair(4L, Vector2i(1, 0))
|
||||
)
|
||||
|
||||
fun puzzle1() {
|
||||
|
||||
val programData = loadProgramData(DAY15_INPUT_PATH)
|
||||
val maze = Maze()
|
||||
val distances = mutableMapOf(Pair(Vector2i(0, 0), 0))
|
||||
pathFind(mutableMapOf(Pair(Vector2i(0, 0), programData)), maze, distances)
|
||||
|
||||
// maze.print()
|
||||
|
||||
val oxygenPosition = maze.find(Cell.OXYGEN)
|
||||
println(distances[oxygenPosition])
|
||||
}
|
||||
|
||||
fun puzzle2() {
|
||||
|
||||
val programData = loadProgramData(DAY15_INPUT_PATH)
|
||||
val maze = Maze()
|
||||
val distances = mutableMapOf(Pair(Vector2i(0, 0), 0))
|
||||
pathFind(mutableMapOf(Pair(Vector2i(0, 0), programData)), maze, distances)
|
||||
|
||||
val oxygenPosition = maze.find(Cell.OXYGEN)
|
||||
val oxygenDistances = mutableMapOf(Pair(oxygenPosition, 0))
|
||||
floodFill(oxygenPosition, maze, oxygenDistances)
|
||||
|
||||
println(oxygenDistances.values.max())
|
||||
}
|
||||
|
||||
fun pathFind(unexplored: MutableMap<Vector2i, LongArray>, maze: Maze, distances: MutableMap<Vector2i, Int>) {
|
||||
|
||||
while (unexplored.isNotEmpty()) {
|
||||
val state = unexplored.minBy { distances[it.key] ?: Int.MAX_VALUE }!!
|
||||
unexplored.remove(state.key)
|
||||
// println("Exploring ${state.key}")
|
||||
for (direction in movementDirections.entries) {
|
||||
val target = state.key + direction.value
|
||||
if (maze[target] == null) {
|
||||
// Move there, find out
|
||||
val program = IntCodeProgram(state.value.copyOf(), StackBasedInputProvider(longArrayOf(direction.key)))
|
||||
when (program.executeUntilOutput()!!) {
|
||||
// Hit a wall
|
||||
0L -> maze[target] = Cell.WALL
|
||||
1L -> {
|
||||
maze[target] = Cell.EMPTY
|
||||
}
|
||||
2L -> {
|
||||
maze[target] = Cell.OXYGEN
|
||||
}
|
||||
}
|
||||
|
||||
distances[target] = distances[state.key]!! + 1
|
||||
|
||||
if (maze[target] != Cell.WALL) {
|
||||
unexplored[target] = program.data
|
||||
}
|
||||
} else {
|
||||
// Check if this path was faster than the existing one
|
||||
if (distances[target]!! > distances[state.key]!! + 1) {
|
||||
error("Found a target that was visited using a longer route? this shouldn't happen...")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun floodFill(pos: Vector2i, maze: Maze, distances: MutableMap<Vector2i, Int>) {
|
||||
|
||||
val distanceToPos = distances[pos]!!
|
||||
for (direction in movementDirections.values) {
|
||||
val target = pos + direction
|
||||
if (maze[target] != null && maze[target] != Cell.WALL) {
|
||||
val targetDistance = distances[target]
|
||||
if (targetDistance == null || targetDistance > distanceToPos + 1) {
|
||||
distances[target] = distanceToPos + 1
|
||||
floodFill(target, maze, distances)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Maze {
|
||||
private val data = mutableMapOf(Pair(Vector2i(0, 0), Cell.EMPTY))
|
||||
|
||||
operator fun get(pos: Vector2i): Cell? = data[pos]
|
||||
operator fun set(pos: Vector2i, cell: Cell) {
|
||||
data[pos] = cell
|
||||
}
|
||||
|
||||
fun print() {
|
||||
|
||||
val min = Vector2i(
|
||||
data.keys.map { it.x }.min()!!,
|
||||
data.keys.map { it.y }.min()!!
|
||||
)
|
||||
val max = Vector2i(
|
||||
data.keys.map { it.x }.max()!!,
|
||||
data.keys.map { it.y }.max()!!
|
||||
)
|
||||
for(y in (min.y..max.y)) {
|
||||
for (x in (min.x..max.x)) {
|
||||
if (x == 0 && y == 0) print("O") else {
|
||||
print(
|
||||
when (data[Vector2i(x, y)]) {
|
||||
null -> " "
|
||||
Cell.EMPTY -> "."
|
||||
Cell.WALL -> "#"
|
||||
Cell.OXYGEN -> "o"
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
println()
|
||||
}
|
||||
}
|
||||
|
||||
fun find(cell: Day15.Cell): Vector2i {
|
||||
return data.entries.first { it.value == cell }.key
|
||||
}
|
||||
}
|
||||
|
||||
enum class Cell {
|
||||
EMPTY, WALL, OXYGEN
|
||||
}
|
||||
|
||||
data class Vector2i(val x: Int, val y: Int) {
|
||||
|
||||
operator fun div(d: Int) = Vector2i(x / d, y / d)
|
||||
operator fun minus(n: Int) = Vector2i(x - n, y - n)
|
||||
operator fun minus(v: Vector2i) = Vector2i(x - v.x, y - v.y)
|
||||
operator fun plus(n: Int) = Vector2i(x + n, y + n)
|
||||
operator fun plus(v: Vector2i) = Vector2i(x + v.x, y + v.y)
|
||||
}
|
||||
}
|
||||
1
src/main/resources/day/15/input.txt
Normal file
1
src/main/resources/day/15/input.txt
Normal file
@@ -0,0 +1 @@
|
||||
3,1033,1008,1033,1,1032,1005,1032,31,1008,1033,2,1032,1005,1032,58,1008,1033,3,1032,1005,1032,81,1008,1033,4,1032,1005,1032,104,99,1001,1034,0,1039,1001,1036,0,1041,1001,1035,-1,1040,1008,1038,0,1043,102,-1,1043,1032,1,1037,1032,1042,1105,1,124,102,1,1034,1039,1002,1036,1,1041,1001,1035,1,1040,1008,1038,0,1043,1,1037,1038,1042,1106,0,124,1001,1034,-1,1039,1008,1036,0,1041,1002,1035,1,1040,1001,1038,0,1043,1002,1037,1,1042,1106,0,124,1001,1034,1,1039,1008,1036,0,1041,1002,1035,1,1040,101,0,1038,1043,1001,1037,0,1042,1006,1039,217,1006,1040,217,1008,1039,40,1032,1005,1032,217,1008,1040,40,1032,1005,1032,217,1008,1039,35,1032,1006,1032,165,1008,1040,35,1032,1006,1032,165,1102,1,2,1044,1105,1,224,2,1041,1043,1032,1006,1032,179,1102,1,1,1044,1105,1,224,1,1041,1043,1032,1006,1032,217,1,1042,1043,1032,1001,1032,-1,1032,1002,1032,39,1032,1,1032,1039,1032,101,-1,1032,1032,101,252,1032,211,1007,0,44,1044,1106,0,224,1102,0,1,1044,1106,0,224,1006,1044,247,1001,1039,0,1034,1002,1040,1,1035,102,1,1041,1036,101,0,1043,1038,1001,1042,0,1037,4,1044,1106,0,0,9,21,23,46,38,21,77,24,34,41,9,82,3,32,97,21,67,23,67,35,41,27,93,13,82,38,74,16,91,25,34,64,47,43,50,15,81,21,30,27,63,88,9,98,95,42,69,23,57,15,52,22,65,43,7,36,90,13,8,83,68,37,6,48,22,53,21,87,86,77,23,14,56,40,32,77,15,9,70,2,28,88,35,37,98,91,29,84,4,62,75,99,40,57,68,35,79,47,78,41,88,20,92,24,76,8,8,51,16,21,75,97,15,71,34,21,77,26,5,98,92,13,94,36,39,61,78,19,96,12,28,3,68,17,8,83,29,50,10,17,46,9,18,56,2,75,53,47,12,66,18,62,67,10,73,35,69,33,58,39,24,68,17,90,77,35,83,22,98,46,6,46,41,45,69,33,12,70,21,47,13,25,54,36,53,23,83,6,31,33,79,55,29,55,42,9,53,25,29,66,60,83,37,9,56,35,2,28,50,84,92,1,50,40,1,59,93,5,85,82,31,74,34,70,28,37,51,50,31,24,83,62,36,29,16,9,93,49,40,13,50,51,54,23,66,88,46,15,31,90,10,59,38,87,36,32,54,71,35,6,24,43,76,53,17,60,41,64,66,12,5,84,22,47,24,94,39,40,51,20,33,61,35,10,9,97,8,79,56,19,59,41,91,67,9,12,70,55,78,78,31,25,45,3,62,10,87,20,17,54,66,14,28,58,3,12,94,80,4,93,93,18,70,92,7,43,30,99,21,81,68,23,19,75,49,42,37,72,14,17,16,50,77,12,33,92,84,26,83,35,52,32,53,5,49,3,94,72,39,51,41,64,4,99,77,67,30,60,52,4,1,75,96,10,12,54,58,4,66,62,84,38,2,46,83,12,33,99,17,3,42,64,84,38,62,6,72,42,20,82,30,36,63,27,75,11,65,16,36,79,9,58,33,48,56,20,11,13,41,65,28,99,15,31,56,89,26,58,5,13,93,24,11,4,25,49,83,96,15,93,60,2,8,86,76,10,41,60,53,13,45,70,33,35,88,38,76,75,26,88,73,52,19,32,88,17,65,35,23,3,74,93,40,77,19,10,57,1,53,12,84,32,39,96,16,55,38,77,52,24,1,58,5,90,88,33,78,36,16,61,22,36,76,64,23,38,56,18,67,32,86,53,21,76,52,34,57,4,19,1,74,67,9,61,80,9,35,31,80,12,97,28,41,72,24,38,64,25,87,21,54,15,84,55,9,33,16,52,51,37,79,43,54,20,98,33,45,89,18,25,33,9,12,52,27,67,62,92,27,95,35,47,13,52,22,63,51,19,50,50,40,19,90,13,67,49,18,83,6,58,9,62,16,74,20,16,51,56,90,36,50,3,48,26,50,31,24,74,83,73,10,55,90,83,4,1,46,21,88,26,56,35,10,77,2,40,90,14,68,27,62,38,6,61,66,10,8,72,35,79,74,38,76,46,43,83,25,25,75,11,18,74,18,3,59,94,22,42,79,85,9,10,26,78,27,13,94,28,57,25,19,59,1,89,54,84,41,9,71,6,30,73,29,58,87,43,61,17,66,9,69,23,58,36,11,45,86,45,28,62,97,6,31,19,99,65,36,58,36,45,3,26,27,33,46,75,19,97,24,65,75,33,15,21,83,98,38,29,77,83,15,62,7,51,86,12,11,37,7,86,9,80,37,92,28,50,52,69,16,55,76,59,9,85,30,97,69,93,13,63,4,74,80,88,31,80,36,51,40,98,95,83,23,92,7,91,63,68,40,73,0,0,21,21,1,10,1,0,0,0,0,0,0
|
||||
Reference in New Issue
Block a user