This commit is contained in:
Chris Hodges 2024-12-15 07:33:07 +01:00
parent 0592f4a862
commit 3ee70151f1
2 changed files with 232 additions and 2 deletions

View File

@ -51,7 +51,7 @@ p=9,5 v=-3,-3
2) px == w/2, py > w/2 % h
*/
val z = Array(robots.size) { IntArray(4) }
for (t in 1..1000000000L) {
for (t in 1..w * h) {
/*val good = robots.all {
val x = ((it[0] + t * (it[2] + w)) % w).toInt()
val y = ((it[1] + t * (it[3] + h)) % h).toInt()
@ -68,7 +68,7 @@ p=9,5 v=-3,-3
z.forEach { grid[it[0], it[1]] = '*' }
grid.debug()
println()
break
return t
}
return 0
}

230
src/aoc2024/Day15.kt Normal file
View File

@ -0,0 +1,230 @@
package aoc2024
import CharGrid
import println
import readInput
/*
--- Day 15: Warehouse Woes ---
https://adventofcode.com/2024/day/15
*/
fun main() {
val inlineTestInput2 = """
##########
#..O..O.O#
#......O.#
#.OO..O.O#
#..O@..O.#
#O#..O...#
#O..O..O.#
#.OO.O.OO#
#....O...#
##########
<vv>^<v^>v>^vv^v>v<>v^v<v<^vv<<<^><<><>>v<vvv<>^v^>^<<<><<v<<<v^vv^v>^
vvv<<^>^v^^><<>>><>^<<><^vv^^<>vvv<>><^^v>^>vv<>v<<<<v<^v>^<^^>>>^<v<v
><>vv>v^v^<>><>>>><^^>vv>v<^^^>>v^v^<^^>v^^>v^<^v>v<>>v^v^<v>v^^<^^vv<
<<v<^>>^^^^>>>v^<>vvv^><v<<<>^^^vv^<vvv>^>v<^^^^v<>^>vvvv><>>v^<<^^^^^
^><^><>>><>^^<<^^v>>><^<v>^<vv>>v>>>^v><>^v><<<<v>>v<v<v>vvv>^<><<>^><
^>><>^v<><^vvv<^^<><v<<<<<><^v<<<><<<^^<v<^^^><^>>^<v^><<<^>>^v<v^v<v^
>^>>^v>vv>^<<^v<>><<><<v<<v><>v<^vv<<<>^^v^>^^>>><<^v>>v^v><^^>>^<>vv^
<><^^>^^^<><vvvvv^v<v<<>^v<v>v<<^><<><<><<<^^<<<^<<>><<><^^^>^^<>^>v<>
^^>vv<^v^v<vv>^<><v<^v>^^^>>>^^vvv^>vvv<>>>^<^>>>>>^<<^v>^vvv<>^<><<v>
v^^>>><<^^<>>^v^<v^vv<>v^<<>^<^v^v><^<<<><<^<v><v<>vv>>v><v^<vv<>v^<<^
"""
val inlineTestInput = """
########
#..O.O.#
##@.O..#
#...O..#
#.#.O..#
#...O..#
#......#
########
<^^>>>vv<v>>v<<
"""
val inlineTestInput3 = """
#######
#...#.#
#.....#
#..OO@#
#..O..#
#.....#
#######
<vv<<^^<<^^
"""
fun part1(input: List<String>): Int {
val splitp = input.withIndex().find { it.value.isEmpty() }!!.index
val grid = CharGrid(input.take(splitp))
val inst = input.drop(splitp).joinToString("")
var (rc, rd) = grid.findMatches { it == '@' }[0]
for (m in inst) {
grid[rc, rd] = '.'
var dc = 0
var dr = 0
when (m) {
'<' -> dc = -1
'>' -> dc = 1
'^' -> dr = -1
'v' -> dr = 1
}
var s = 1
while (grid[rc + dc * s, rd + dr * s] != '.') {
if (grid[rc + dc * s, rd + dr * s] == '#') {
s = 0
break
}
s++
}
if (s > 0) {
if (s > 1) {
grid[rc + dc * s, rd + dr * s] = 'O'
}
rc += dc
rd += dr
}
grid[rc, rd] = '@'
}
return grid.generateGridPos().filter { grid[it] == 'O' }.sumOf { it.dc + it.dr * 100 }
}
fun canMove(grid: CharGrid, bc: Int, rd: Int, dr: Int): Boolean {
if ((grid[bc, rd] == '[')) {
val c1 = grid[bc, rd + dr]
val c2 = grid[bc + 1, rd + dr]
if ((c1 == '.') && (c2 == '.')) return true
if ((c1 == '#') || (c2 == '#')) return false
if ((c1 == '[')) return canMove(grid, bc, rd + dr, dr)
return (if (c1 == ']') canMove(grid, bc - 1, rd + dr, dr) else true)
&& (if (c2 == '[') canMove(grid, bc + 1, rd + dr, dr) else true)
} else if ((grid[bc, rd] == ']')) {
return canMove(grid, bc - 1, rd, dr)
} else {
throw IllegalStateException()
}
}
fun doMove(grid: CharGrid, bc: Int, rd: Int, dr: Int) {
if ((grid[bc, rd] == '[')) {
val c1 = grid[bc, rd + dr]
val c2 = grid[bc + 1, rd + dr]
if ((c1 == '[')) {
doMove(grid, bc, rd + dr, dr)
} else {
if (c1 == ']') doMove(grid, bc - 1, rd + dr, dr)
if (c2 == '[') doMove(grid, bc + 1, rd + dr, dr)
}
if ((grid[bc, rd + dr] == '.') && (grid[bc + 1, rd + dr] == '.')) {
grid[bc, rd + dr] = '['
grid[bc + 1, rd + dr] = ']'
grid[bc, rd] = '.'
grid[bc + 1, rd] = '.'
} else {
throw IllegalStateException()
}
} else if ((grid[bc, rd] == ']')) {
doMove(grid, bc - 1, rd, dr)
}
}
fun part2(input: List<String>): Int {
val splitp = input.withIndex().find { it.value.isEmpty() }!!.index
val sgrid = CharGrid(input.take(splitp))
val grid = CharGrid(sgrid.width * 2, sgrid.height)
sgrid.generateGridPos().forEach {
when (val cc = sgrid[it]) {
'@' -> {
grid[it.dc * 2, it.dr] = cc
grid[it.dc * 2 + 1, it.dr] = '.'
}
'O' -> {
grid[it.dc * 2, it.dr] = '['
grid[it.dc * 2 + 1, it.dr] = ']'
}
else -> {
grid[it.dc * 2, it.dr] = cc
grid[it.dc * 2 + 1, it.dr] = cc
}
}
}
val inst = input.drop(splitp).joinToString("")
var (rc, rd) = grid.findMatches { it == '@' }[0]
for (m in inst) {
grid[rc, rd] = '.'
var dc = 0
var dr = 0
when (m) {
'<' -> dc = -1
'>' -> dc = 1
'^' -> dr = -1
'v' -> dr = 1
}
if (dc != 0) {
var s = 1
var bc: Char? = null
while (grid[rc + dc * s, rd] != '.') {
val cc = grid[rc + dc * s, rd]
if (cc == '#') {
s = 0
break
} else {
if (bc != null && cc == bc) {
s = 0
break
}
bc = cc
}
s++
}
if (s > 0) {
if (s > 1) {
for (p in s downTo 1) {
grid[rc + dc * p, rd] = grid[rc + dc * (p - 1), rd]
}
}
rc += dc
rd += dr
}
} else {
if (grid[rc, rd + dr] != '.') {
if (grid[rc, rd + dr] != '#') {
if (canMove(grid, rc, rd + dr, dr)) {
doMove(grid, rc, rd + dr, dr)
rc += dc
rd += dr
}
}
} else {
rc += dc
rd += dr
}
}
grid[rc, rd] = '@'
}
return grid.generateGridPos().filter { grid[it] == '[' }.sumOf { it.dc + it.dr * 100 }
}
// test if implementation meets criteria from the description, like:
val testInput = inlineTestInput.trim().reader().readLines()
val testInput2 = inlineTestInput2.trim().reader().readLines()
val testInput3 = inlineTestInput3.trim().reader().readLines()
//val testInput = readInput("aoc2024/Day15_test")
val testInputPart1Result = part1(testInput)
println("Part 1 Test: $testInputPart1Result")
val testInputPart2Result = part2(testInput2)
println("Part 2 Test: $testInputPart2Result")
check(testInputPart1Result == 2028)
check(testInputPart2Result == 9021)
val input = readInput("aoc2024/Day15")
part1(input).println()
part2(input).println()
}