Day 12, at least it works
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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 =
|
||||
|
||||
74
aoc/src/dev/ctsk/aoc/days/Day12.scala
Normal file
74
aoc/src/dev/ctsk/aoc/days/Day12.scala
Normal 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))
|
||||
)
|
||||
Reference in New Issue
Block a user