Day 6 part 2 :'-(
Change-Id: I04ba157f88233e3f57632f632c4a60267e486058
This commit is contained in:
parent
3cc10ea7c3
commit
d2487ed762
20
src/Utils.kt
20
src/Utils.kt
@ -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) {
|
||||
|
@ -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
|
||||
}
|
||||
c += dir.dc
|
||||
r += dir.dr
|
||||
}
|
||||
grid.debug()
|
||||
return grid.findMatches { it == 'O' }.count()
|
||||
for (op in obstaclePos) {
|
||||
grid[op] = '#'
|
||||
if (checkLooping(grid, RelPos(oc, or))) {
|
||||
solutions.add(op)
|
||||
}
|
||||
grid[op] = '.'
|
||||
}
|
||||
return solutions.size
|
||||
}
|
||||
|
||||
// test if implementation meets criteria from the description, like:
|
||||
|
Loading…
Reference in New Issue
Block a user