diff --git a/src/Utils.kt b/src/Utils.kt index 30c0a12..37117a0 100644 --- a/src/Utils.kt +++ b/src/Utils.kt @@ -75,6 +75,13 @@ class CharGrid { val data: Array val bChar: Char + constructor(width: Int, height: Int, borderChar: Char = ' ') { + bChar = borderChar + this.width = width + this.height = height + data = Array(height) { CharArray(width) { bChar } } + } + constructor(input: List, borderChar: Char = ' ') { bChar = borderChar width = input[0].length @@ -196,6 +203,9 @@ class CharGrid { fun matchRelative(c: Int, r: Int, relposes: Iterable, predicate: (char: Char) -> Boolean): List = relposes.filter { predicate(get(c + it.dc, r + it.dr)) } + fun matchRelativeRelPos(pos: RelPos, relposes: Iterable, predicate: (char: Char) -> Boolean): List = + relposes.filter { predicate(get(pos.translate(it))) } + fun matchAbsoluteRelPos(pos: RelPos, relposes: Iterable, predicate: (char: Char) -> Boolean): List = relposes.map { pos.translate(it) }.filter { predicate(get(it)) } diff --git a/src/aoc2024/Day12.kt b/src/aoc2024/Day12.kt index 5ee77bd..0fcab9e 100644 --- a/src/aoc2024/Day12.kt +++ b/src/aoc2024/Day12.kt @@ -54,53 +54,29 @@ MMMISSJEEE fun part2(input: List): Int { val grid = CharGrid(input) var sum = 0 + val magic = listOf(3, 5, 10, 12) for (p in grid.generateGridPos()) { val c = grid[p] if (c != '.') { - println("$p: $c") val areaPos = HashSet() - val fence = HashSet() var newPos = setOf(p) while (newPos.isNotEmpty()) { val newSeeds = HashSet() for (np in newPos) { areaPos.add(np) - grid[np] = c.lowercaseChar() + grid[np] = '.' newSeeds.addAll(grid.matchAbsoluteRelPos(np, CharGrid.PLUS_POS) { it == c }) - fence.addAll(grid.matchRelative(np.dc, np.dr, CharGrid.BOX_POS) { it.uppercaseChar() != c } - .map { RelPos(np.dc * 2 + it.dc, np.dr * 2 + it.dr) }) } newPos = newSeeds } - var turns = 0 - while (fence.isNotEmpty()) { - val f1 = fence.first() - var dir = CharGrid.PLUS_POS.find { fence.contains(f1.translate(it)) } - if (dir == null) { - fence.remove(f1) - turns += 2 - break - } - - // 851006 too low - // 852491 too high - val initDir = dir - var rp = f1 - while (fence.isNotEmpty()) { - fence.remove(rp) - if (fence.contains(rp.translate(dir!!))) { - rp = rp.translate(dir) - } else { - dir = CharGrid.PLUS_POS.find { fence.contains(rp.translate(it)) } ?: break - rp = rp.translate(dir) - turns++ - } - } - if (initDir != dir) turns++ + val corners = areaPos.sumOf { + val plusCode = CharGrid.PLUS_POS.mapIndexed { index, relPos -> if (areaPos.contains(it.translate(relPos))) 1 shl index else 0 }.sum() + val crossCode = CharGrid.CROSS_POS.mapIndexed { index, relPos -> if (areaPos.contains(it.translate(relPos))) 1 shl index else 0 }.sum() + val outer = magic.count { plusCode and it == 0 } + val inner = magic.filterIndexed { i, m -> (plusCode and m == m) && (crossCode and (1 shl i) == 0) }.count() + outer + inner } - println("$c Area: ${areaPos.size} Fence: ${fence.size} Discount: $turns = ${areaPos.size * turns}") - areaPos.forEach { grid[it] = '.' } - sum += areaPos.size * turns + sum += areaPos.size * corners } } return sum