1
0
Fork 0

day(20): refactor

• move ‹square› to ‹Point›
• factor out range construction
• convert ‹TrenchMap.print› into ‹TrenchMap.toString›
• use ‹reduce› instead of ‹fold› in ‹TrenchMap.toIndex›
• factor out iterative enhancement

Signed-off-by: Matej Focko <mfocko@redhat.com>
This commit is contained in:
Matej Focko 2021-12-20 11:40:50 +01:00
parent 186a70f34d
commit 56de6f7110

View file

@ -2,10 +2,10 @@ package year2021.day20
import readInput import readInput
data class Point(val x: Int, val y: Int) data class Point(val x: Int, val y: Int) {
val square: Iterable<Point>
fun getSquare(pixel: Point): Iterable<Point> = get() = (y - 1..y + 1).flatMap { y -> (x - 1..x + 1).map { x -> Point(x, y) } }
(pixel.y - 1..pixel.y + 1).flatMap { y -> (pixel.x - 1..pixel.x + 1).map { x -> Point(x, y) } } }
data class TrenchMap( data class TrenchMap(
val algorithm: List<Char>, val algorithm: List<Char>,
@ -15,28 +15,27 @@ data class TrenchMap(
fun get(key: Point): Char = map.getOrDefault(key, default) fun get(key: Point): Char = map.getOrDefault(key, default)
fun get(x: Int, y: Int): Char = get(Point(x, y)) fun get(x: Int, y: Int): Char = get(Point(x, y))
private fun coordinateRange(getter: (Point) -> Int): IntRange =
(map.keys.minOf(getter) - 1..map.keys.maxOf(getter) + 1)
private val xs: IntRange private val xs: IntRange
get() = (map.keys.minOf { it.x } - 2..map.keys.maxOf { it.x } + 2) get() = coordinateRange { it.x }
private val ys: IntRange private val ys: IntRange
get() = (map.keys.minOf { it.y } - 2..map.keys.maxOf { it.y } + 2) get() = coordinateRange { it.y }
private val indices: Iterable<Point> private val indices: Iterable<Point>
get() = ys.flatMap { y -> xs.map { x -> Point(x, y) } } get() = ys.flatMap { y -> xs.map { x -> Point(x, y) } }
fun print() { override fun toString(): String =
for (y in ys) { ys.joinToString("\n") { y ->
for (x in xs) { xs.joinToString("") { x -> get(x, y).toString() }
print(get(x, y))
}
println()
} }
}
private fun toIndex(square: Iterable<Point>): Int = private fun toIndex(square: Iterable<Point>): Int =
square.map { if (get(it) == '#') 1 else 0 }.fold(0) { acc, bit -> acc * 2 + bit } square.map { if (get(it) == '#') 1 else 0 }.reduce { acc, bit -> acc * 2 + bit }
private fun enhancePixel(pixel: Point): Char = algorithm[toIndex(getSquare(pixel))] private fun enhancePixel(pixel: Point): Char = algorithm[toIndex(pixel.square)]
fun enhance(): TrenchMap = fun enhance(): TrenchMap =
TrenchMap( TrenchMap(
@ -45,7 +44,7 @@ data class TrenchMap(
when (default) { when (default) {
'.' -> algorithm.first() '.' -> algorithm.first()
'#' -> algorithm.last() '#' -> algorithm.last()
else -> error("Invalid char found") else -> error("Invalid default char found")
} }
) )
} }
@ -59,11 +58,11 @@ fun List<String>.toTrenchMap(): TrenchMap =
}.toMap() }.toMap()
) )
fun part1(input: TrenchMap): Int = fun enhance(input: TrenchMap, steps: Int): Int =
(1..2).fold(input) { acc, i -> acc.enhance() }.map.values.count { it == '#' } (1..steps).fold(input) { image, _ -> image.enhance() }.map.values.count { it == '#' }
fun part2(input: TrenchMap): Int = fun part1(input: TrenchMap): Int = enhance(input, 2)
(1..50).fold(input) { acc, i -> acc.enhance() }.map.values.count { it == '#' } fun part2(input: TrenchMap): Int = enhance(input, 50)
fun main() { fun main() {
val sample = readInput(20, "sample").toTrenchMap() val sample = readInput(20, "sample").toTrenchMap()