diff --git a/src/Utils.kt b/src/Utils.kt index 37117a0..5527ab9 100644 --- a/src/Utils.kt +++ b/src/Utils.kt @@ -96,10 +96,8 @@ class CharGrid { height = inputGrid.size } - @Deprecated("Use RelPos version instead") operator fun get(col: Int, row: Int) = getOrNull(col, row) ?: bChar - @Deprecated("Use RelPos version instead") operator fun set(col: Int, row: Int, newChar: Char?) { if (newChar != null && isInside(col, row)) data[row][col] = newChar } diff --git a/src/aoc2024/Day14.kt b/src/aoc2024/Day14.kt new file mode 100644 index 0000000..9958ecc --- /dev/null +++ b/src/aoc2024/Day14.kt @@ -0,0 +1,89 @@ +package aoc2024 + +import CharGrid +import println +import readInput + +/* +--- Day 14: Restroom Redoubt --- +https://adventofcode.com/2024/day/14 +*/ +fun main() { + + val inlineTestInput = """ +p=0,4 v=3,-3 +p=6,3 v=-1,-3 +p=10,3 v=-1,2 +p=2,0 v=2,-1 +p=0,0 v=1,3 +p=3,0 v=-2,-2 +p=7,6 v=-1,-3 +p=3,0 v=-1,-2 +p=9,3 v=2,3 +p=7,3 v=-1,2 +p=2,4 v=2,-3 +p=9,5 v=-3,-3 +""" + + fun part1(input: List, time: Int, w: Int, h: Int): Int { + val robots = input.map { "p=(\\d+),(\\d+) v=(-?\\d+),(-?\\d+)".toRegex().find(it)!!.groupValues.drop(1).map { it.toInt() }.toIntArray() } + for (r in robots) { + r[0] = (r[0] + time * (r[2] + w)) % w + r[1] = (r[1] + time * (r[3] + h)) % h + } + val q1 = robots.count { it[0] < w / 2 && it[1] < h / 2 } + val q2 = robots.count { it[0] > w / 2 && it[1] < h / 2 } + val q3 = robots.count { it[0] < w / 2 && it[1] > h / 2 } + val q4 = robots.count { it[0] > w / 2 && it[1] > h / 2 } + return q1 * q2 * q3 * q4 + } + + fun part2(input: List, w: Int, h: Int): Int { + val robots = input.map { "p=(\\d+),(\\d+) v=(-?\\d+),(-?\\d+)".toRegex().find(it)!!.groupValues.drop(1).map { it.toInt() }.toIntArray() } + /* + either: 1) x == w/2 -+ c, y == c c in [0..w/2] + or : 2) x == w/2, y in (w/2..h) + + 1) px + t * (vx + w) % w = w/2 - c; py + t * (vy + h) % h = c + px + t * (vx + w) % w = w/2 - (py + t * (vy + h) % h) + (px - py) + t * (((vx + w) % w) - ((vy + h) % h)) = w/2 + + 2) px == w/2, py > w/2 % h + */ + val z = Array(robots.size) { IntArray(4) } + for (t in 1..1000000000L) { + /*val good = robots.all { + val x = ((it[0] + t * (it[2] + w)) % w).toInt() + val y = ((it[1] + t * (it[3] + h)) % h).toInt() + (y <= w / 2 && ((x >= w / 2 - y) && (x <= w / 2 + y))) || (x == w / 2 && y > w / 2) + } + if (!good) continue*/ + for ((i, r) in robots.withIndex()) { + z[i][0] = ((r[0] + t * (r[2] + w)) % w).toInt() + z[i][1] = ((r[1] + t * (r[3] + h)) % h).toInt() + } + if (z.map { it[0] to it[1] }.distinct().count() < robots.size) continue + println("Solution $t") + val grid = CharGrid(w, h, '.') + z.forEach { grid[it[0], it[1]] = '*' } + grid.debug() + println() + break + } + return 0 + } + + // test if implementation meets criteria from the description, like: + val testInput = inlineTestInput.trim().reader().readLines() + //val testInput = readInput("aoc2024/Day14_test") + val testInputPart1Result = part1(testInput, 100, 11, 7) + println("Part 1 Test: $testInputPart1Result") + //val testInputPart2Result = part2(testInput, 11, 7) + //println("Part 2 Test: $testInputPart2Result") + check(testInputPart1Result == 12) + //check(testInputPart2Result == 0) + + val input = readInput("aoc2024/Day14") + part1(input, 100, 101, 103).println() + part2(input, 101, 103).println() +}