59 lines
1.9 KiB
Scala
59 lines
1.9 KiB
Scala
package de.qwertyuiop.aoc.`2021`
|
|
|
|
import de.qwertyuiop.aoc.lib.*
|
|
import cats.*, cats.implicits.given
|
|
|
|
import Vectors.{*, given}
|
|
|
|
def day11(using InputSource): Unit =
|
|
import Octopodes.*
|
|
val fieldRaw = inputF(_.map(_ - '0').toVector)(Vector)
|
|
val field = (
|
|
for
|
|
x <- 0 until fieldRaw.size
|
|
y <- 0 until fieldRaw(0).size
|
|
yield Vec2D(x,y) -> fieldRaw(x)(y)
|
|
).toMap
|
|
|
|
val r = render(fieldRaw.size, fieldRaw(0).size)
|
|
|
|
|
|
val (finalField, finalFlashes) =
|
|
(1 to 100).foldLeft((field, 0)){ case ((field, flashes), _) =>
|
|
val (newField, newFlashes) = energize(field)
|
|
(newField, flashes + newFlashes)
|
|
}
|
|
println(s"After $finalFlashes flashes:")
|
|
r(finalField)
|
|
|
|
val inSync = findSync(field, 0)
|
|
println(s"In sync after $inSync steps")
|
|
|
|
|
|
object Octopodes:
|
|
def render(xSize: Int, ySize: Int)(field: Map[Vec2D[Int], Int]) =
|
|
for x <- 0 until xSize do
|
|
for y <- 0 until ySize do
|
|
print(field(Vec2D(x,y)).toHexString)
|
|
println()
|
|
|
|
def energize(f: Map[Vec2D[Int], Int]): (Map[Vec2D[Int], Int], Int) =
|
|
@annotation.tailrec
|
|
def flashOctopodes(f: Map[Vec2D[Int], Int], flashed: Set[Vec2D[Int]]): (Map[Vec2D[Int], Int], Int) =
|
|
val flashing = f.filter((coord, v) => v > 9).keySet &~ flashed
|
|
if flashing.isEmpty then
|
|
(f.view.mapValues(v => if v > 9 then 0 else v).toMap, flashed.size + flashing.size)
|
|
else
|
|
val neighs = flashing.toVector.flatMap(_.neighbours).occurrences
|
|
val newF = f.map((coord, v) => coord -> (
|
|
if v > 9 || flashing.contains(coord) then 12
|
|
else (v + neighs.getOrElse(coord, 0)).min(11)
|
|
))
|
|
flashOctopodes(newF, flashed | flashing)
|
|
flashOctopodes(f.mapValuesS(_ + 1), Set.empty)
|
|
|
|
def findSync(f: Map[Vec2D[Int], Int], step: Int): Int =
|
|
val (newField, newFlashes) = energize(f)
|
|
if newFlashes == f.size then step + 1
|
|
else findSync(newField, step + 1)
|