From b78c91e5dbc37a8263305a88fbc3aad8c774dcc0 Mon Sep 17 00:00:00 2001 From: Matej Focko Date: Fri, 6 Dec 2024 13:12:03 +0100 Subject: [PATCH] day(06): refactor Signed-off-by: Matej Focko --- src/Day06.kt | 77 ++++++++++++++++++++++------------------------------ 1 file changed, 32 insertions(+), 45 deletions(-) diff --git a/src/Day06.kt b/src/Day06.kt index 1f270b2..aeb5230 100644 --- a/src/Day06.kt +++ b/src/Day06.kt @@ -1,9 +1,11 @@ +private typealias Vector = Pair + class Day06( inputType: String, ) : Day() { private val map: Array = readInput(6, inputType).map { it.toCharArray() }.toTypedArray() - private val initialPosition: Pair = + private val initialPosition: Vector = let { for (row in map.withIndex()) { for (cell in row.value.withIndex()) { @@ -16,76 +18,61 @@ class Day06( error("there's always at least one guard") } - private val route: Set> = - let { - var pos = initialPosition - var direction = 0 to -1 - - val seen = mutableSetOf>() - while (inBounds(pos)) { - seen.add(pos) - - var next = move(pos, direction) - while (!canMoveTo(next)) { - direction = rotate(direction) - next = move(pos, direction) - } - - pos = next - } - - return@let seen - } + private val route: Set = guard(null).let { (visited, _) -> visited.map { (_, p) -> p }.toSet() } override fun precompute() { // no-op } - private fun inBounds(p: Pair): Boolean = + private fun inBounds(p: Vector): Boolean = p.let { (x, y) -> y >= 0 && y < map.size && x >= 0 && x < map[y].size } private fun move( - p: Pair, - d: Pair, - ): Pair { + p: Vector, + d: Vector, + ): Vector { val (x, y) = p val (dx, dy) = d return x + dx to y + dy } - private fun canMoveTo(p: Pair): Boolean = + private fun canMoveTo(p: Vector): Boolean = p.let { (x, y) -> !inBounds(p) || map[y][x] != '#' } - private fun rotate(d: Pair): Pair = + private fun rotate(d: Vector): Vector = d.let { (dx, dy) -> -dy to dx } + private fun guard(obstacle: Vector?): Pair>, Vector> { + var pos = initialPosition + var direction = 0 to -1 + + val visited = mutableSetOf>() + while (inBounds(pos) && !visited.contains(direction to pos)) { + visited.add(direction to pos) + + var next = move(pos, direction) + while (next == obstacle || !canMoveTo(next)) { + direction = rotate(direction) + next = move(pos, direction) + } + + pos = next + } + + return visited to pos + } + override fun part1(): Int = route.size override fun part2(): Int = - route.filter { it != initialPosition }.count { o -> - var pos = initialPosition - var direction = 0 to -1 - - val visited = mutableSetOf, Pair>>() - while (inBounds(pos) && !visited.contains(direction to pos)) { - visited.add(direction to pos) - - var next = move(pos, direction) - while (next == o || !canMoveTo(next)) { - direction = rotate(direction) - next = move(pos, direction) - } - - pos = next - } - - inBounds(pos) + route.filter { it != initialPosition }.count { + guard(it).let { (_, pos) -> inBounds(pos) } } }