From 1b2332a49e6cc7826e4123e09c07468876cb5783 Mon Sep 17 00:00:00 2001 From: chrisly42 Date: Wed, 18 Dec 2024 07:05:44 +0100 Subject: [PATCH] Day 18. --- src/Utils.kt | 4 +- src/aoc2024/Day18.kt | 127 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 src/aoc2024/Day18.kt diff --git a/src/Utils.kt b/src/Utils.kt index 5527ab9..cf0cafd 100644 --- a/src/Utils.kt +++ b/src/Utils.kt @@ -75,11 +75,11 @@ class CharGrid { val data: Array val bChar: Char - constructor(width: Int, height: Int, borderChar: Char = ' ') { + constructor(width: Int, height: Int, borderChar: Char = ' ', fillChar: Char = borderChar) { bChar = borderChar this.width = width this.height = height - data = Array(height) { CharArray(width) { bChar } } + data = Array(height) { CharArray(width) { fillChar } } } constructor(input: List, borderChar: Char = ' ') { diff --git a/src/aoc2024/Day18.kt b/src/aoc2024/Day18.kt new file mode 100644 index 0000000..1c562c4 --- /dev/null +++ b/src/aoc2024/Day18.kt @@ -0,0 +1,127 @@ +package aoc2024 + +import CharGrid +import RelPos +import println +import readInput +import splitInts +import java.util.* + +/* +--- Day 18: RAM Run --- +https://adventofcode.com/2024/day/18 +*/ +fun main() { + + val inlineTestInput = """ +5,4 +4,2 +4,5 +3,0 +2,1 +6,3 +2,4 +1,5 +0,6 +3,3 +2,6 +5,1 +1,2 +5,5 +2,5 +6,5 +1,4 +0,4 +6,4 +1,1 +6,1 +1,0 +0,5 +1,6 +2,0 +""" + + data class Node(val pos: RelPos, val relLen: Int) + + fun part1(input: List, steps: Int, wh: Int): Int { + val posList = input.map { it.splitInts(",").toIntArray() } + val grid = CharGrid(wh, wh, '#', fillChar = '.') + posList.take(steps).forEach { grid[it[0], it[1]] = '#' } + val queue = PriorityQueue(Comparator.comparing { -it.pos.dc - it.pos.dr }) + queue.add(Node(RelPos(0, 0), 0)) + val bestCosts = HashMap() + var minCost = Int.MAX_VALUE + while (queue.isNotEmpty()) { + val node = queue.remove() + val pos = node.pos + val cost = node.relLen + if (pos.dc == wh - 1 && pos.dr == wh - 1) { + minCost = minCost.coerceAtMost(cost) + continue + } + if ((bestCosts[pos] ?: Int.MAX_VALUE) < cost) { + continue + } + bestCosts[pos] = cost + queue.addAll(CharGrid.PLUS_POS + .map { pos.translate(it) } + .filter { grid[it] == '.' && (bestCosts[it] ?: Int.MAX_VALUE) > cost + 1 } + .map { Node(it, cost + 1) }) + } + return minCost + } + + fun part2(input: List, wh: Int): RelPos { + val posList = input.map { it.splitInts(",").toIntArray() } + var lowerBound = 0 + var higherBound = posList.size + do { + val grid = CharGrid(wh, wh, '#', fillChar = '.') + val boulderPos = (lowerBound + higherBound) / 2 + posList.take(boulderPos).forEach { grid[it[0], it[1]] = '#' } + + var foundPath = false + val queue = PriorityQueue(Comparator.comparing { -it.pos.dc - it.pos.dr }) + queue.add(Node(RelPos(0, 0), 0)) + val bestCosts = HashMap() + while (queue.isNotEmpty()) { + val node = queue.remove() + val pos = node.pos + val cost = node.relLen + if (pos.dc == wh - 1 && pos.dr == wh - 1) { + foundPath = true + break + } + if ((bestCosts[pos] ?: Int.MAX_VALUE) < cost) { + continue + } + bestCosts[pos] = cost + queue.addAll(CharGrid.PLUS_POS + .map { pos.translate(it) } + .filter { grid[it] == '.' && (bestCosts[it] ?: Int.MAX_VALUE) > cost + 1 } + .map { Node(it, cost + 1) }) + } + if (foundPath) { + lowerBound = boulderPos + 1 + } else { + higherBound = boulderPos + } + } while (lowerBound < higherBound) + println("$lowerBound $higherBound") + return RelPos(posList[lowerBound - 1][0], posList[lowerBound - 1][1]) + } + + // test if implementation meets criteria from the description, like: + val testInput = inlineTestInput.trim().reader().readLines() + //val testInput = readInput("aoc2024/Day18_test") + val testInputPart1Result = part1(testInput, 12, 7) + println("Part 1 Test: $testInputPart1Result") + val testInputPart2Result = part2(testInput, 7) + println("Part 2 Test: $testInputPart2Result") + check(testInputPart1Result == 22) + check(testInputPart2Result == RelPos(6, 1)) + + val input = readInput("aoc2024/Day18") + part1(input, 1024, 71).println() + part2(input, 71).println() +}