aboutsummaryrefslogtreecommitdiff
path: root/aoc-2021-kotlin/src/Day20.kt
diff options
context:
space:
mode:
authortchojnacki <tomaszchojnacki2001@gmail.com>2022-08-13 12:25:41 +0200
committertchojnacki <tomaszchojnacki2001@gmail.com>2022-08-13 12:25:41 +0200
commit992d24939100a6adb466b23449a62c36736b4249 (patch)
tree778ff441bb0a14ac64aca2d6dde67b4133e566a0 /aoc-2021-kotlin/src/Day20.kt
parent2ef3cacc7766c55f3e40803e37864acc4bd4c918 (diff)
downloadgleam_aoc2020-992d24939100a6adb466b23449a62c36736b4249.tar.gz
gleam_aoc2020-992d24939100a6adb466b23449a62c36736b4249.zip
Finish day 20
Diffstat (limited to 'aoc-2021-kotlin/src/Day20.kt')
-rw-r--r--aoc-2021-kotlin/src/Day20.kt60
1 files changed, 60 insertions, 0 deletions
diff --git a/aoc-2021-kotlin/src/Day20.kt b/aoc-2021-kotlin/src/Day20.kt
new file mode 100644
index 0000000..9bc3b01
--- /dev/null
+++ b/aoc-2021-kotlin/src/Day20.kt
@@ -0,0 +1,60 @@
+object Day20 {
+ private class Enhancement private constructor(
+ private val algorithm: BooleanArray,
+ private val initialImage: Set<Pos2D>
+ ) {
+ companion object {
+ fun fromString(string: String) = string.split("\n\n").let { (algorithm, image) ->
+ Enhancement(
+ algorithm.map { it == '#' }.toBooleanArray(),
+ image
+ .split("\n")
+ .withIndex()
+ .flatMap { (y, row) ->
+ row.withIndex().mapNotNull { (x, char) -> if (char == '#') Pos2D(x, y) else null }
+ }
+ .toSet()
+ )
+ }
+ }
+
+ private fun nextStateFor(currentImage: Set<Pos2D>, pos: Pos2D) = combinations(1 downTo -1)
+ .map { (dy, dx) -> if (currentImage.contains(pos + Pos2D(dx, dy))) 1 else 0 }
+ .withIndex()
+ .sumOf { (index, value) -> value shl index }
+ .let { algorithm[it] }
+
+ fun enhance(times: Int): Int {
+ return generateSequence(StepState.initial(initialImage)) { (image, topLeft, bottomRight) ->
+ StepState(
+ combinations(topLeft.y..bottomRight.y, topLeft.x..bottomRight.x)
+ .mapNotNull { (y, x) ->
+ Pos2D(x, y).let { if (nextStateFor(image, it)) it else null }
+ }.toSet(),
+ topLeft + Pos2D(1, 1),
+ bottomRight - Pos2D(1, 1)
+ )
+ }.drop(times).first().image.size
+ }
+ }
+
+ private data class StepState(val image: Set<Pos2D>, val topLeft: Pos2D, val bottomRight: Pos2D) {
+ companion object {
+ fun initial(image: Set<Pos2D>) = StepState(image, Pos2D(-100, -100), Pos2D(200, 200))
+ }
+ }
+
+ fun part1(input: String) = Enhancement.fromString(input).enhance(2)
+
+ fun part2(input: String) = Enhancement.fromString(input).enhance(50)
+}
+
+fun main() {
+ val testInput = readInputAsString("Day20_test")
+ check(Day20.part1(testInput) == 35)
+ check(Day20.part2(testInput) == 3351)
+
+ val input = readInputAsString("Day20")
+ println(Day20.part1(input))
+ println(Day20.part2(input))
+}