Day 6 part 2 :'-(

Change-Id: I04ba157f88233e3f57632f632c4a60267e486058
This commit is contained in:
Chris Hodges 2024-12-06 12:31:43 +01:00
parent 3cc10ea7c3
commit d2487ed762
2 changed files with 59 additions and 44 deletions

View File

@ -94,6 +94,9 @@ class CharGrid {
if (newChar != null && isInside(col, row)) data[row][col] = newChar
}
operator fun get(pos: RelPos) = get(pos.dc, pos.dr)
operator fun set(pos: RelPos, newChar: Char?) = set(pos.dc, pos.dr, newChar)
fun setOrThrow(col: Int, row: Int, newChar: Char) {
if (!isInside(col, row)) throw IndexOutOfBoundsException("$col, $row out of bounds")
set(col, row, newChar)
@ -101,12 +104,14 @@ class CharGrid {
fun getOrNull(col: Int, row: Int) = if (isInside(col, row)) data[row][col] else null
fun isInside(col: Int, row: Int) = (col in 0 until width) && (row in 0 until height)
fun isInside(pos: RelPos) = isInside(pos.dc, pos.dr)
fun getHorizNumberValueAt(rp: RelPos) = getHorizNumberValueAt(rp.dc, rp.dr)
fun getHorizNumberValueAt(col: Int, row: Int): Pair<Int, List<RelPos>> {
val relPos = getHorizNumberRelPosAt(col, row)
return relPos.map { this[col + it.dc, row + it.dr].digitToInt() }.reduce { acc, digit -> acc * 10 + digit } to relPos
return relPos.map { this[col + it.dc, row + it.dr].digitToInt() }
.reduce { acc, digit -> acc * 10 + digit } to relPos
}
fun getHorizNumberRelPosAt(col: Int, row: Int): List<RelPos> {
@ -159,9 +164,13 @@ class CharGrid {
relposes.map { get(c + it.dc, r + it.dr) }
}
fun countStrings(relposeList: Iterable<Iterable<RelPos>>, string: String) = findMatches(relposeList) { it == string }.count()
fun countStrings(relposeList: Iterable<Iterable<RelPos>>, string: String) =
findMatches(relposeList) { it == string }.count()
fun findMatches(relposeList: Iterable<Iterable<RelPos>>, predicate: (content: String) -> Boolean): List<Pair<String, RelPos>> {
fun findMatches(
relposeList: Iterable<Iterable<RelPos>>,
predicate: (content: String) -> Boolean
): List<Pair<String, RelPos>> {
val matches = ArrayList<Pair<String, RelPos>>()
for (r in 0 until height) {
for (c in 0 until width) {
@ -176,7 +185,10 @@ class CharGrid {
return matches
}
fun findCombinedMatches(relposeList: Iterable<Iterable<RelPos>>, predicate: (content: List<String>) -> Boolean): List<RelPos> {
fun findCombinedMatches(
relposeList: Iterable<Iterable<RelPos>>,
predicate: (content: List<String>) -> Boolean
): List<RelPos> {
val matches = ArrayList<RelPos>()
for (r in 0 until height) {
for (c in 0 until width) {

View File

@ -109,67 +109,70 @@ fun main() {
fun part1(input: List<String>): Int {
val grid = CharGrid(input, '.')
var (c, r) = grid.findMatches { it == '^' }[0]
val (oc, or) = grid.findMatches { it == '^' }[0]
var pos = RelPos(oc, or)
var dir = RelPos(0, -1)
while (grid.isInside(c, r)) {
grid[c, r] = 'X'
if (grid[c + dir.dc, r + dir.dr] == '#') {
while (grid.isInside(pos)) {
grid[pos] = 'X'
while (grid[pos.translate(dir)] == '#') {
dir = RelPos(-dir.dr, dir.dc)
}
c += dir.dc
r += dir.dr
pos = pos.translate(dir)
}
return grid.findMatches { it == 'X' }.count()
}
fun looping(grid: CharGrid, origDirGrid: Array<IntArray>, oc: Int, or: Int, origDir: RelPos, origDirBit: Int): Boolean {
val dirgrid = Array(grid.height) { origDirGrid[it].copyOf() }
var dir = origDir
var c = oc
var r = or
var dirBit = origDirBit
while (grid.isInside(c, r)) {
if ((dirgrid[c][r] and (1 shl dirBit)) != 0) {
return true
fun checkLooping(grid: CharGrid, origPos: RelPos): Boolean {
val dirgrid = Array(grid.height) { IntArray(grid.width) }
var dir = RelPos(0, -1)
var dirBit = 0
var looping = false
var pos = origPos
while (grid.isInside(pos)) {
if ((dirgrid[pos.dc][pos.dr] and (1 shl dirBit)) != 0) {
looping = true
break
}
dirgrid[c][r] = dirgrid[c][r] or (1 shl dirBit)
if (grid[c + dir.dc, r + dir.dr] == '#') {
dirgrid[pos.dc][pos.dr] = dirgrid[pos.dc][pos.dr] or (1 shl dirBit)
while (grid[pos.translate(dir)] == '#') {
dir = RelPos(-dir.dr, dir.dc)
dirBit = (dirBit + 1) and 3
}
c += dir.dc
r += dir.dr
pos = pos.translate(dir)
}
return false
return looping
}
fun part2(input: List<String>): Int {
val grid = CharGrid(input, '.')
val dirgrid = Array(grid.height) { IntArray(grid.width) }
var (oc, or) = grid.findMatches { it == '^' }[0]
var c = oc
var r = or
val obstaclePos = HashSet<RelPos>()
val solutions = HashSet<RelPos>()
val (oc, or) = grid.findMatches { it == '^' }[0]
var pos = RelPos(oc, or)
var dir = RelPos(0, -1)
var dirBit = 0
while (grid.isInside(c, r)) {
val newDir = RelPos(-dir.dr, dir.dc)
//grid[c, r] = 'X'
dirgrid[c][r] = dirgrid[c][r] or (1 shl dirBit)
if (grid[c + dir.dc, r + dir.dr] == '#') {
dir = newDir
dirBit = (dirBit + 1) and 3
while (true) {
grid[pos] = 'X'
val newPos = pos.translate(dir)
if (!grid.isInside(newPos)) break
if (grid[newPos] == '#') {
dir = RelPos(-dir.dr, dir.dc)
} else {
if (looping(grid, dirgrid, c + newDir.dc, r + newDir.dr, newDir, (dirBit + 1) and 3)) {
if ((c + dir.dc != oc) || (r + dir.dr != or)) {
grid[c + dir.dc, r + dir.dr] = 'O'
if (grid[newPos] == '.') {
obstaclePos.add(newPos)
}
pos = newPos
}
}
for (op in obstaclePos) {
grid[op] = '#'
if (checkLooping(grid, RelPos(oc, or))) {
solutions.add(op)
}
c += dir.dc
r += dir.dr
grid[op] = '.'
}
grid.debug()
return grid.findMatches { it == 'O' }.count()
return solutions.size
}
// test if implementation meets criteria from the description, like: