Day 12 finally. I hate you.

This commit is contained in:
Chris Hodges 2024-12-12 21:37:24 +01:00
parent 9a8b316122
commit 90cf5a8335
2 changed files with 19 additions and 33 deletions

View File

@ -75,6 +75,13 @@ class CharGrid {
val data: Array<CharArray> val data: Array<CharArray>
val bChar: Char 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<String>, borderChar: Char = ' ') { constructor(input: List<String>, borderChar: Char = ' ') {
bChar = borderChar bChar = borderChar
width = input[0].length width = input[0].length
@ -196,6 +203,9 @@ class CharGrid {
fun matchRelative(c: Int, r: Int, relposes: Iterable<RelPos>, predicate: (char: Char) -> Boolean): List<RelPos> = fun matchRelative(c: Int, r: Int, relposes: Iterable<RelPos>, predicate: (char: Char) -> Boolean): List<RelPos> =
relposes.filter { predicate(get(c + it.dc, r + it.dr)) } relposes.filter { predicate(get(c + it.dc, r + it.dr)) }
fun matchRelativeRelPos(pos: RelPos, relposes: Iterable<RelPos>, predicate: (char: Char) -> Boolean): List<RelPos> =
relposes.filter { predicate(get(pos.translate(it))) }
fun matchAbsoluteRelPos(pos: RelPos, relposes: Iterable<RelPos>, predicate: (char: Char) -> Boolean): List<RelPos> = fun matchAbsoluteRelPos(pos: RelPos, relposes: Iterable<RelPos>, predicate: (char: Char) -> Boolean): List<RelPos> =
relposes.map { pos.translate(it) }.filter { predicate(get(it)) } relposes.map { pos.translate(it) }.filter { predicate(get(it)) }

View File

@ -54,53 +54,29 @@ MMMISSJEEE
fun part2(input: List<String>): Int { fun part2(input: List<String>): Int {
val grid = CharGrid(input) val grid = CharGrid(input)
var sum = 0 var sum = 0
val magic = listOf(3, 5, 10, 12)
for (p in grid.generateGridPos()) { for (p in grid.generateGridPos()) {
val c = grid[p] val c = grid[p]
if (c != '.') { if (c != '.') {
println("$p: $c")
val areaPos = HashSet<RelPos>() val areaPos = HashSet<RelPos>()
val fence = HashSet<RelPos>()
var newPos = setOf(p) var newPos = setOf(p)
while (newPos.isNotEmpty()) { while (newPos.isNotEmpty()) {
val newSeeds = HashSet<RelPos>() val newSeeds = HashSet<RelPos>()
for (np in newPos) { for (np in newPos) {
areaPos.add(np) areaPos.add(np)
grid[np] = c.lowercaseChar() grid[np] = '.'
newSeeds.addAll(grid.matchAbsoluteRelPos(np, CharGrid.PLUS_POS) { it == c }) 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 newPos = newSeeds
} }
var turns = 0 val corners = areaPos.sumOf {
while (fence.isNotEmpty()) { val plusCode = CharGrid.PLUS_POS.mapIndexed { index, relPos -> if (areaPos.contains(it.translate(relPos))) 1 shl index else 0 }.sum()
val f1 = fence.first() val crossCode = CharGrid.CROSS_POS.mapIndexed { index, relPos -> if (areaPos.contains(it.translate(relPos))) 1 shl index else 0 }.sum()
var dir = CharGrid.PLUS_POS.find { fence.contains(f1.translate(it)) } val outer = magic.count { plusCode and it == 0 }
if (dir == null) { val inner = magic.filterIndexed { i, m -> (plusCode and m == m) && (crossCode and (1 shl i) == 0) }.count()
fence.remove(f1) outer + inner
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++
} }
println("$c Area: ${areaPos.size} Fence: ${fence.size} Discount: $turns = ${areaPos.size * turns}") sum += areaPos.size * corners
areaPos.forEach { grid[it] = '.' }
sum += areaPos.size * turns
} }
} }
return sum return sum