Skip to content

Commit

Permalink
Solve 2024 day 12 part 2
Browse files Browse the repository at this point in the history
  • Loading branch information
sim642 committed Dec 12, 2024
1 parent 12e3d98 commit a23086e
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 10 deletions.
56 changes: 50 additions & 6 deletions src/main/scala/eu/sim642/adventofcode2024/Day12.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ import eu.sim642.adventofcodelib.GridImplicits.*
import eu.sim642.adventofcodelib.box.Box
import eu.sim642.adventofcodelib.graph.{BFS, GraphComponents}
import eu.sim642.adventofcodelib.pos.Pos
import eu.sim642.adventofcode2018.Day13.DirectionPos

object Day12 {

case class Edge(in: Pos, out: Pos)

case class Region(poss: Set[Pos]) {
def area: Int = poss.size

Expand All @@ -17,6 +20,34 @@ object Day12 {
.map(pos => Pos.axisOffsets.map(pos + _).count(poss)) //.tapEach(println)
.sum
}

def sides: Int = {
val edges =
for {
pos <- poss
offset <- Pos.axisOffsets
newPos = pos + offset
if !poss(newPos)
} yield Edge(pos, newPos)

val graphComponents = new GraphComponents[Edge] {
override def nodes: IterableOnce[Edge] = edges

override def unitNeighbors(edge: Edge): IterableOnce[Edge] = {
val Edge(in, out) = edge
val direction = out - in
for {
inOffset <- Seq(direction.left, direction.right)
newIn = in + inOffset
newOut = newIn + direction
newEdge = Edge(newIn, newOut)
if edges(newEdge)
} yield newEdge
}
}

BFS.components(graphComponents).size
}
}

def regions(grid: Grid[Char]): Set[Region] = {
Expand All @@ -37,18 +68,31 @@ object Day12 {
BFS.components(graphComponents).map(x => Region(x.toSet)).toSet // TODO: avoid weird toSet-s
}

def totalFencingPrice(grid: Grid[Char]): Int = {
val regs = regions(grid)
//for (region <- regs)
// println(s"${grid(region.poss.head)}: area=${region.area} perimeter=${region.perimeter}")
regs.iterator.map(region => region.area * region.perimeter).sum
trait Part {
def regionFencingPrice(region: Region): Int

def totalFencingPrice(grid: Grid[Char]): Int = {
val regs = regions(grid)
//for (region <- regs)
// println(s"${grid(region.poss.head)}: area=${region.area} perimeter=${region.perimeter}")
regs.iterator.map(regionFencingPrice).sum
}
}

object Part1 extends Part {
override def regionFencingPrice(region: Region): Int = region.area * region.perimeter
}

object Part2 extends Part {
override def regionFencingPrice(region: Region): Int = region.area * region.sides
}

def parseGrid(input: String): Grid[Char] = input.linesIterator.map(_.toVector).toVector

lazy val input: String = scala.io.Source.fromInputStream(getClass.getResourceAsStream("day12.txt")).mkString.trim

def main(args: Array[String]): Unit = {
println(totalFencingPrice(parseGrid(input)))
println(Part1.totalFencingPrice(parseGrid(input)))
println(Part2.totalFencingPrice(parseGrid(input)))
}
}
35 changes: 31 additions & 4 deletions src/test/scala/eu/sim642/adventofcode2024/Day12Test.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,40 @@ class Day12Test extends AnyFunSuite {
|MIIISIJEEE
|MMMISSJEEE""".stripMargin

val exampleInput4 =
"""EEEEE
|EXXXX
|EEEEE
|EXXXX
|EEEEE""".stripMargin

val exampleInput5 =
"""AAAAAA
|AAABBA
|AAABBA
|ABBAAA
|ABBAAA
|AAAAAA""".stripMargin

test("Part 1 examples") {
assert(totalFencingPrice(parseGrid(exampleInput)) == 140)
assert(totalFencingPrice(parseGrid(exampleInput2)) == 772)
assert(totalFencingPrice(parseGrid(exampleInput3)) == 1930)
assert(Part1.totalFencingPrice(parseGrid(exampleInput)) == 140)
assert(Part1.totalFencingPrice(parseGrid(exampleInput2)) == 772)
assert(Part1.totalFencingPrice(parseGrid(exampleInput3)) == 1930)
}

test("Part 1 input answer") {
assert(totalFencingPrice(parseGrid(input)) == 1433460)
assert(Part1.totalFencingPrice(parseGrid(input)) == 1433460)
}

test("Part 2 examples") {
assert(Part2.totalFencingPrice(parseGrid(exampleInput)) == 80)
assert(Part2.totalFencingPrice(parseGrid(exampleInput2)) == 436)
assert(Part2.totalFencingPrice(parseGrid(exampleInput4)) == 236)
assert(Part2.totalFencingPrice(parseGrid(exampleInput5)) == 368)
assert(Part2.totalFencingPrice(parseGrid(exampleInput3)) == 1206)
}

test("Part 2 input answer") {
assert(Part2.totalFencingPrice(parseGrid(input)) == 855082)
}
}

0 comments on commit a23086e

Please sign in to comment.