Day 20.
This commit is contained in:
parent
9047a97185
commit
aa0f1dad74
104
src/aoc2024/Day20.kt
Normal file
104
src/aoc2024/Day20.kt
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
package aoc2024
|
||||||
|
|
||||||
|
import CharGrid
|
||||||
|
import RelPos
|
||||||
|
import println
|
||||||
|
import readInput
|
||||||
|
import kotlin.math.abs
|
||||||
|
|
||||||
|
/*
|
||||||
|
--- Day 20: Race Condition ---
|
||||||
|
https://adventofcode.com/2024/day/20
|
||||||
|
*/
|
||||||
|
fun main() {
|
||||||
|
|
||||||
|
val inlineTestInput = """
|
||||||
|
###############
|
||||||
|
#...#...#.....#
|
||||||
|
#.#.#.#.#.###.#
|
||||||
|
#S#...#.#.#...#
|
||||||
|
#######.#.#.###
|
||||||
|
#######.#.#...#
|
||||||
|
#######.#.###.#
|
||||||
|
###..E#...#...#
|
||||||
|
###.#######.###
|
||||||
|
#...###...#...#
|
||||||
|
#.#####.#.###.#
|
||||||
|
#.#...#.#.#...#
|
||||||
|
#.#.#.#.#.#.###
|
||||||
|
#...#...#...###
|
||||||
|
###############
|
||||||
|
"""
|
||||||
|
|
||||||
|
data class Node(val pos: RelPos, val relLen: Int)
|
||||||
|
|
||||||
|
fun getPathCosts(grid: CharGrid, startPos: RelPos, endPos: RelPos): HashMap<RelPos, Int> {
|
||||||
|
val queue = ArrayDeque<Node>()
|
||||||
|
queue.add(Node(startPos, 0))
|
||||||
|
val bestCosts = HashMap<RelPos, Int>()
|
||||||
|
while (queue.isNotEmpty()) {
|
||||||
|
val node = queue.removeFirst()
|
||||||
|
val pos = node.pos
|
||||||
|
val cost = node.relLen
|
||||||
|
bestCosts[pos] = cost
|
||||||
|
if (pos == endPos) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
queue.addAll(CharGrid.PLUS_POS
|
||||||
|
.map { pos.translate(it) }
|
||||||
|
.filter { grid[it] == '.' && !bestCosts.contains(it) }
|
||||||
|
.map { Node(it, cost + 1) })
|
||||||
|
}
|
||||||
|
return bestCosts
|
||||||
|
}
|
||||||
|
|
||||||
|
fun part1(input: List<String>): Int {
|
||||||
|
val grid = CharGrid(input)
|
||||||
|
val start = grid.findMatchesRelPos { it == 'S' }[0]
|
||||||
|
val end = grid.findMatchesRelPos { it == 'E' }[0]
|
||||||
|
grid[end] = '.'
|
||||||
|
|
||||||
|
val cheats = listOf(
|
||||||
|
RelPos(0, -1), RelPos(-1, 0), RelPos(1, 0), RelPos(0, 1),
|
||||||
|
RelPos(0, -2), RelPos(-2, 0), RelPos(2, 0), RelPos(0, 2),
|
||||||
|
)
|
||||||
|
val pathCosts = getPathCosts(grid, start, end)
|
||||||
|
|
||||||
|
return pathCosts.asSequence().sumOf { (pos, cost) ->
|
||||||
|
cheats.map { pos.translate(it) to (abs(it.dr) + abs(it.dc)) }
|
||||||
|
.filter { (pathCosts[it.first] ?: 0) - (cost + it.second) >= 100 }
|
||||||
|
.map { it.first to (pathCosts[it.first]!! - (cost + it.second)) }.count()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun part2(input: List<String>): Int {
|
||||||
|
val grid = CharGrid(input)
|
||||||
|
val start = grid.findMatchesRelPos { it == 'S' }[0]
|
||||||
|
val end = grid.findMatchesRelPos { it == 'E' }[0]
|
||||||
|
grid[end] = '.'
|
||||||
|
|
||||||
|
val pathCosts = getPathCosts(grid, start, end)
|
||||||
|
|
||||||
|
// manhattan distance!
|
||||||
|
val pathCostsList = pathCosts.toList()
|
||||||
|
return pathCostsList.sumOf { (pos, cost) ->
|
||||||
|
pathCostsList.asSequence().filter { abs(pos.dc - it.first.dc) + abs(pos.dr - it.first.dr) <= 20 }
|
||||||
|
.filter { (pathCosts[it.first] ?: 0) - (cost + abs(pos.dc - it.first.dc) + abs(pos.dr - it.first.dr)) >= 100 }
|
||||||
|
.map { it.first to (pathCosts[it.first]!! - (cost + it.second)) }.count()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// test if implementation meets criteria from the description, like:
|
||||||
|
val testInput = inlineTestInput.trim().reader().readLines()
|
||||||
|
//val testInput = readInput("aoc2024/Day20_test")
|
||||||
|
val testInputPart1Result = part1(testInput)
|
||||||
|
println("Part 1 Test: $testInputPart1Result")
|
||||||
|
val testInputPart2Result = part2(testInput)
|
||||||
|
println("Part 2 Test: $testInputPart2Result")
|
||||||
|
check(testInputPart1Result == 0)
|
||||||
|
check(testInputPart2Result == 0)
|
||||||
|
|
||||||
|
val input = readInput("aoc2024/Day20")
|
||||||
|
part1(input).println()
|
||||||
|
part2(input).println()
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user