@@ -5,6 +5,7 @@ import eu.sim642.adventofcodelib.Grid
55import eu .sim642 .adventofcodelib .GridImplicits .*
66import eu .sim642 .adventofcodelib .cycle .BrentCycleFinder
77import eu .sim642 .adventofcodelib .pos .Pos
8+ import eu .sim642 .adventofcodelib .IteratorImplicits ._
89
910object Day6 {
1011
@@ -49,11 +50,19 @@ object Day6 {
4950
5051 def countObstructionPoss (input : Input ): Int = { // TODO: optimize?
5152 val Input (grid, guard) = input
52- guardPoss(input)
53- .iterator
54- .filter(obstructionPos => obstructionPos != guard.pos)
55- .map(obstructionPos => Input (grid.updatedGrid(obstructionPos, true ), guard))
56- .count(isGuardCycle)
53+ iterateGuard(input) // only consider obstacles on initial path
54+ .takeWhile(guard => input.grid.containsPos(guard.pos))
55+ .scanLeft((Set .empty[Pos ], Guard (Pos (- 1 , - 1 ), Pos .zero)))({ case ((acc, prevGuard), guard) => (acc + prevGuard.pos, guard) }) // incrementally compute guardPoss
56+ // TODO: scanLeftMap or something
57+ .tail // ignore first scanLeft element with dummy guard
58+ .filter({ case (acc, guard) => ! acc.contains(guard.pos) }) // keep only those positions that are being visited for the first time
59+ .map(_._2)
60+ .zipWithTail
61+ // .filter(obstructionPos => obstructionPos != guard.pos)
62+ .count({ case (guard, obstruction) =>
63+ val newGrid = grid.updatedGrid(obstruction.pos, true ) // place obstacle in front of guard
64+ isGuardCycle(Input (newGrid, guard)) // check cycle starting from previous guard
65+ })
5766 }
5867
5968 def parseGrid (input : String ): Grid [Boolean ] = input.linesIterator.map(_.toVector).toVector.mapGrid({
0 commit comments