Day 12, at least it works

This commit is contained in:
Christian
2024-12-12 21:43:44 +01:00
parent 2f960f83eb
commit b00c5c369e
5 changed files with 224 additions and 1 deletions

View File

@@ -61,3 +61,9 @@ class Grid[A](val data: Array[Array[A]]):
def contains(p: Point): Boolean =
p.x >= 0 && p.y >= 0 && p.x < height && p.y < width
def points: Seq[Point] =
for
x <- data.indices
y <- data(x).indices
yield Point(x, y)

View File

@@ -13,7 +13,8 @@ val solvers = Map[Int, Solver](
8 -> Day08,
9 -> Day09,
10 -> Day10,
11 -> Day11
11 -> Day11,
12 -> Day12
)
def runSolver(solver: Solver, input: os.Path): Unit =

View File

@@ -0,0 +1,74 @@
package dev.ctsk.aoc.days
import dev.ctsk.aoc.*
import dev.ctsk.aoc.Direction.*
import collection.mutable
import scala.collection.mutable.ArrayBuffer
object Day12 extends Solver(12):
case class Plots(
layout: Grid[Int],
edges: Map[Int, Array[(Point, Direction)]],
sizes: Map[Int, Int]
)
def mapPlots(grid: Grid[Char]): Plots =
val layout = Grid(Array.fill(grid.height, grid.width)(-1))
val edges = mutable.Map.empty[Int, Array[(Point, Direction)]]
val sizes = mutable.Map.empty[Int, Int]
def fill(start: Point, label: Int): Unit =
layout(start) = label
val edge = ArrayBuffer.empty[(Point, Direction)]
val plant = grid(start).get
var size = 1
def rec(current: Point): Unit =
for
dir <- Seq(Up, Down, Left, Right)
next = dir(current)
do
grid(next) match
case Some(p) if p == plant =>
if layout(next).contains(-1) then {
layout(next) = label
size += 1
rec(next)
}
case Some(_) => edge += ((current, dir))
case None => edge += ((current, dir))
rec(start)
edges(label) = edge.toArray
sizes(label) = size
for
p <- grid.points
if layout(p).contains(-1)
do fill(p, sizes.size)
// grid.points.zipWithIndex.foreach(fill)
Plots(layout, edges.toMap, sizes.toMap)
def part1(plots: Plots): Int =
plots.sizes.map((k, v) => v * plots.edges(k).length).sum
def part2(plots: Plots): Int =
plots.sizes
.map((id, size) =>
val edge = plots.edges(id).toSet
val corners = edge -- edge.map((pt, dir) => (dir.turnRight(pt), dir))
size * corners.size
)
.sum
override def run(input: os.ReadablePath): (Timings, Solution) =
val grid = Grid(os.read.lines(input).map(_.toArray).toArray)
val (pre_time, plots) = timed { mapPlots(grid) }
val (p1_time, p1_solution) = timed { part1(plots) }
val (p2_time, p2_solution) = timed { part2(plots) }
(
Timings(pre_time, p1_time, p2_time),
Solution(Int.box(p1_solution), Int.box(p2_solution))
)