Skip to content

Commit

Permalink
Optimize and clean up 2023 day 10 part 2
Browse files Browse the repository at this point in the history
  • Loading branch information
sim642 committed Dec 10, 2023
1 parent 49fcc3a commit 6afb50e
Showing 1 changed file with 26 additions and 42 deletions.
68 changes: 26 additions & 42 deletions src/main/scala/eu/sim642/adventofcode2023/Day10.scala
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package eu.sim642.adventofcode2023

import eu.sim642.adventofcodelib.Grid
import eu.sim642.adventofcodelib.GridImplicits.*
import eu.sim642.adventofcodelib.graph.{BFS, Distances, GraphTraversal, UnitNeighbors}
import eu.sim642.adventofcodelib.pos.Pos
import eu.sim642.adventofcodelib.GridImplicits.*

import scala.annotation.tailrec

object Day10 {

Expand Down Expand Up @@ -42,62 +40,48 @@ object Day10 {
def enclosedTiles(grid: Grid[Char]): Int = {
val loop = findLoop(grid).nodes

val startAlternative = {
val pos = grid.posOf('S')
val newOffsets = for {
offset <- pipeDirections(grid(pos))
newPos = pos + offset
if grid.containsPos(newPos)
if grid(newPos) != '.'
if pipeDirections(grid(newPos)).contains(-offset)
} yield offset
pipeDirections.find(_._2 == newOffsets).get._1
}

// grid with only loop: unconnected pipes removed and start pipe determined
val loopGrid = {
// TODO: use view for zipWithIndex?
for ((row, y) <- grid.zipWithIndex)
yield for ((cell, x) <- row.zipWithIndex)
yield {
val pos = Pos(x, y)
if (cell == 'S')
startAlternative
if (cell == 'S') {
val newOffsets = for {
offset <- pipeDirections(cell)
newPos = pos + offset
if grid.containsPos(newPos)
if grid(newPos) != '.'
if pipeDirections(grid(newPos)).contains(-offset)
} yield offset
pipeDirections.find(_._2 == newOffsets).get._1
}
else if (loop.contains(pos))
cell
else
'.'
}
}

def isInside(pos: Pos): Boolean = {

@tailrec
def helper(pos: Pos, count: Int): Boolean = {
val newPos = pos + Pos(1, 0)
if (grid.containsPos(newPos)) {
loopGrid(newPos) match {
case '|' | 'F' | '7' => helper(newPos, count + 1)
case '.' | 'L' | 'J' => helper(newPos, count)
case '-' => helper(newPos, count)
case a => throw IllegalArgumentException(s"$a")
}
}
else {
count % 2 == 1
}
}

helper(pos, 0)
// grid with pipe crossing count parity
val insideGrid = {
for (row <- loopGrid)
yield row.scanLeft(false)({ // cast ray from left to right
case (inside, '|' | 'L' | 'J') => !inside // consider pipe crossing at the top of tile
case (inside, _) => inside
})
}

(for {
(row, y) <- loopGrid.view.zipWithIndex
(cell, x) <- row.view.zipWithIndex
if cell == '.'
if isInside(Pos(x, y))
} yield 1).sum
(loopGrid lazyZip insideGrid)
.map((loopRow, insideRow) =>
(loopRow lazyZip insideRow)
.count((cell, inside) => cell == '.' && inside)
)
.sum
}


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

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

0 comments on commit 6afb50e

Please sign in to comment.