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
|
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) {
|
fun setOrThrow(col: Int, row: Int, newChar: Char) {
|
||||||
if (!isInside(col, row)) throw IndexOutOfBoundsException("$col, $row out of bounds")
|
if (!isInside(col, row)) throw IndexOutOfBoundsException("$col, $row out of bounds")
|
||||||
set(col, row, newChar)
|
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 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(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(rp: RelPos) = getHorizNumberValueAt(rp.dc, rp.dr)
|
||||||
|
|
||||||
fun getHorizNumberValueAt(col: Int, row: Int): Pair<Int, List<RelPos>> {
|
fun getHorizNumberValueAt(col: Int, row: Int): Pair<Int, List<RelPos>> {
|
||||||
val relPos = getHorizNumberRelPosAt(col, row)
|
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> {
|
fun getHorizNumberRelPosAt(col: Int, row: Int): List<RelPos> {
|
||||||
@ -159,9 +164,13 @@ class CharGrid {
|
|||||||
relposes.map { get(c + it.dc, r + it.dr) }
|
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>>()
|
val matches = ArrayList<Pair<String, RelPos>>()
|
||||||
for (r in 0 until height) {
|
for (r in 0 until height) {
|
||||||
for (c in 0 until width) {
|
for (c in 0 until width) {
|
||||||
@ -176,7 +185,10 @@ class CharGrid {
|
|||||||
return matches
|
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>()
|
val matches = ArrayList<RelPos>()
|
||||||
for (r in 0 until height) {
|
for (r in 0 until height) {
|
||||||
for (c in 0 until width) {
|
for (c in 0 until width) {
|
||||||
|
@ -109,67 +109,70 @@ fun main() {
|
|||||||
|
|
||||||
fun part1(input: List<String>): Int {
|
fun part1(input: List<String>): Int {
|
||||||
val grid = CharGrid(input, '.')
|
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)
|
var dir = RelPos(0, -1)
|
||||||
while (grid.isInside(c, r)) {
|
while (grid.isInside(pos)) {
|
||||||
grid[c, r] = 'X'
|
grid[pos] = 'X'
|
||||||
if (grid[c + dir.dc, r + dir.dr] == '#') {
|
while (grid[pos.translate(dir)] == '#') {
|
||||||
dir = RelPos(-dir.dr, dir.dc)
|
dir = RelPos(-dir.dr, dir.dc)
|
||||||
}
|
}
|
||||||
c += dir.dc
|
pos = pos.translate(dir)
|
||||||
r += dir.dr
|
|
||||||
}
|
}
|
||||||
return grid.findMatches { it == 'X' }.count()
|
return grid.findMatches { it == 'X' }.count()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun looping(grid: CharGrid, origDirGrid: Array<IntArray>, oc: Int, or: Int, origDir: RelPos, origDirBit: Int): Boolean {
|
fun checkLooping(grid: CharGrid, origPos: RelPos): Boolean {
|
||||||
val dirgrid = Array(grid.height) { origDirGrid[it].copyOf() }
|
val dirgrid = Array(grid.height) { IntArray(grid.width) }
|
||||||
var dir = origDir
|
var dir = RelPos(0, -1)
|
||||||
var c = oc
|
var dirBit = 0
|
||||||
var r = or
|
var looping = false
|
||||||
var dirBit = origDirBit
|
var pos = origPos
|
||||||
while (grid.isInside(c, r)) {
|
while (grid.isInside(pos)) {
|
||||||
if ((dirgrid[c][r] and (1 shl dirBit)) != 0) {
|
if ((dirgrid[pos.dc][pos.dr] and (1 shl dirBit)) != 0) {
|
||||||
return true
|
looping = true
|
||||||
|
break
|
||||||
}
|
}
|
||||||
dirgrid[c][r] = dirgrid[c][r] or (1 shl dirBit)
|
dirgrid[pos.dc][pos.dr] = dirgrid[pos.dc][pos.dr] or (1 shl dirBit)
|
||||||
if (grid[c + dir.dc, r + dir.dr] == '#') {
|
while (grid[pos.translate(dir)] == '#') {
|
||||||
dir = RelPos(-dir.dr, dir.dc)
|
dir = RelPos(-dir.dr, dir.dc)
|
||||||
dirBit = (dirBit + 1) and 3
|
dirBit = (dirBit + 1) and 3
|
||||||
}
|
}
|
||||||
c += dir.dc
|
pos = pos.translate(dir)
|
||||||
r += dir.dr
|
|
||||||
}
|
}
|
||||||
return false
|
return looping
|
||||||
}
|
}
|
||||||
|
|
||||||
fun part2(input: List<String>): Int {
|
fun part2(input: List<String>): Int {
|
||||||
val grid = CharGrid(input, '.')
|
val grid = CharGrid(input, '.')
|
||||||
val dirgrid = Array(grid.height) { IntArray(grid.width) }
|
val obstaclePos = HashSet<RelPos>()
|
||||||
var (oc, or) = grid.findMatches { it == '^' }[0]
|
val solutions = HashSet<RelPos>()
|
||||||
var c = oc
|
val (oc, or) = grid.findMatches { it == '^' }[0]
|
||||||
var r = or
|
|
||||||
|
var pos = RelPos(oc, or)
|
||||||
var dir = RelPos(0, -1)
|
var dir = RelPos(0, -1)
|
||||||
var dirBit = 0
|
while (true) {
|
||||||
while (grid.isInside(c, r)) {
|
grid[pos] = 'X'
|
||||||
val newDir = RelPos(-dir.dr, dir.dc)
|
val newPos = pos.translate(dir)
|
||||||
//grid[c, r] = 'X'
|
if (!grid.isInside(newPos)) break
|
||||||
dirgrid[c][r] = dirgrid[c][r] or (1 shl dirBit)
|
if (grid[newPos] == '#') {
|
||||||
if (grid[c + dir.dc, r + dir.dr] == '#') {
|
dir = RelPos(-dir.dr, dir.dc)
|
||||||
dir = newDir
|
|
||||||
dirBit = (dirBit + 1) and 3
|
|
||||||
} else {
|
} else {
|
||||||
if (looping(grid, dirgrid, c + newDir.dc, r + newDir.dr, newDir, (dirBit + 1) and 3)) {
|
if (grid[newPos] == '.') {
|
||||||
if ((c + dir.dc != oc) || (r + dir.dr != or)) {
|
obstaclePos.add(newPos)
|
||||||
grid[c + dir.dc, r + dir.dr] = 'O'
|
}
|
||||||
|
pos = newPos
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (op in obstaclePos) {
|
||||||
|
grid[op] = '#'
|
||||||
|
if (checkLooping(grid, RelPos(oc, or))) {
|
||||||
|
solutions.add(op)
|
||||||
}
|
}
|
||||||
c += dir.dc
|
grid[op] = '.'
|
||||||
r += dir.dr
|
|
||||||
}
|
}
|
||||||
grid.debug()
|
return solutions.size
|
||||||
return grid.findMatches { it == 'O' }.count()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// test if implementation meets criteria from the description, like:
|
// test if implementation meets criteria from the description, like:
|
||||||
|
Loading…
Reference in New Issue
Block a user