Skip to content

Commit

Permalink
Dump top-down solver stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
sim642 committed Dec 16, 2023
1 parent 210de7a commit eab4c00
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 47 deletions.
108 changes: 74 additions & 34 deletions src/main/scala/eu/sim642/adventofcode2023/Day16.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,50 +13,56 @@ object Day16 {

case class Beam(pos: Pos, direction: Pos)

def countEnergized(grid: Grid[Char], startBeam: Beam = Beam(Pos.zero, Pos(1, 0))): Int = {

val graphTraversal = new GraphTraversal[Beam] with UnitNeighbors[Beam] {
override val startNode: Beam = startBeam

override def unitNeighbors(beam: Beam): IterableOnce[Beam] = {
val Beam(pos, direction) = beam
val newDirections =
grid(pos) match {
case '.' => Iterator(direction)
case '/' => Iterator(direction.reflectMinor)
case '\\' => Iterator(direction.reflectMajor)
case '|' if direction.x == 0 => Iterator(direction)
case '-' if direction.y == 0 => Iterator(direction)
case '|' | '-' => Iterator(direction.left, direction.right)
}
for {
newDirection <- newDirections
newPos = pos + newDirection
if grid.containsPos(newPos)
} yield Beam(newPos, newDirection)
}
def countEnergized0(grid: Grid[Char]): Beam => Int = {

def unitNeighbors(beam: Beam): IterableOnce[Beam] = {
val Beam(pos, direction) = beam
val newDirections =
grid(pos) match {
case '.' => Iterator(direction)
case '/' => Iterator(direction.reflectMinor)
case '\\' => Iterator(direction.reflectMajor)
case '|' if direction.x == 0 => Iterator(direction)
case '-' if direction.y == 0 => Iterator(direction)
case '|' | '-' => Iterator(direction.left, direction.right)
}
for {
newDirection <- newDirections
newPos = pos + newDirection
if grid.containsPos(newPos)
} yield Beam(newPos, newDirection)
}

def f(x: Beam)(get: Beam => Set[Pos]): Set[Pos] =
//graphTraversal.unitNeighbors(x).iterator.flatMap(get).toSet + x.pos
graphTraversal.unitNeighbors(x).iterator.map(get).foldLeft(Set.empty[Pos])(_ ++ _) + x.pos
//unitNeighbors(x).iterator.flatMap(get).toSet + x.pos
unitNeighbors(x).iterator.map(get).foldLeft(Set.empty[Pos])(_ ++ _) + x.pos

val stable = mutable.Set.empty[Beam]
val called = mutable.Set.empty[Beam]
val infl = mutable.Map.empty[Beam, Set[Beam]].withDefaultValue(Set.empty[Beam])
val infl = mutable.Map.empty[Beam, mutable.Set[Beam]].withDefault(_ => mutable.Set.empty[Beam])
val rho = mutable.Map.empty[Beam, Set[Pos]].withDefaultValue(Set.empty[Pos])

var indent = 0

def destabilize(x: Beam): Unit = {
println(s"${" " * indent}destab $x")
val w = infl(x)
infl(x) = Set.empty
//infl(x) = Set.empty
infl.remove(x)
for (y <- w) {
println(s"${" " * indent}stable remove $y")
stable -= y
if (!called(y))
if (!called(y)) {
indent += 1
destabilize(y)
indent -= 1
}
}
}

def eval(x: Beam)(y: Beam): Set[Pos] = {
//infl(y) += x
//solve(y)
solve(y)
infl(y) += x
rho(y)
Expand All @@ -65,37 +71,71 @@ object Day16 {

@tailrec
def solve(x: Beam): Unit = {
println((rho.size, stable.size, called.size))
println(s"${" " * indent}solve $x")
//println((rho.size, stable.size, called.size))
if (!stable(x) && !called(x)) {
stable += x
//println(s"${" " * indent}stable add $x")
//stable += x
called += x
indent += 1
//val tmp = rho(x) union f(x)(eval(x))
val tmp = f(x)(eval(x))
indent -= 1
called -= x
if (rho(x) != tmp) {
println(s" ${tmp.size}")
//println(s" ${tmp.size}")
rho(x) = tmp
destabilize(x)
//stable -= x
solve(x)
}
else {
println(s"${" " * indent}stable add $x")
stable += x
}
}
else if (!called(x)) {
assert(stable(x))
called += x
indent += 1
//val tmp = rho(x) union f(x)(eval(x))
val tmp = f(x)(eval(x))
indent -= 1
called -= x
if (rho(x) != tmp) {
val x1 = rho(x) -- tmp
val x2 = tmp -- rho(x)
println(s"STABLE CHANGE $x $x1 $x2")
throw new IllegalStateException()
}
}
}


//println(DFS.traverse(graphTraversal).nodes.size)
//DFS.traverse(graphTraversal).nodes.map(_.pos).size

solve(graphTraversal.startNode)
//print(rho)
rho(graphTraversal.startNode).size
beam => {
println(s"$beam: ${stable(beam)} ${rho(beam).size} ${stable}")
solve(beam)
assert(stable(beam))
assert(called.isEmpty)
//infl.clear()
//stable.clear()
//print(rho)
rho(beam).size
}
}

def countEnergized(grid: Grid[Char], startBeam: Beam = Beam(Pos.zero, Pos(1, 0))): Int =
countEnergized0(grid)(startBeam)

def maxEnergized(grid: Grid[Char]): Int = {
val top = grid(0).indices.map(x => Beam(Pos(x, 0), Pos(0, 1)))
val bottom = grid(0).indices.map(x => Beam(Pos(x, grid.size - 1), Pos(0, -1)))
val left = grid.indices.map(y => Beam(Pos(0, y), Pos(1, 0)))
val right = grid.indices.map(y => Beam(Pos(grid(0).size - 1, y), Pos(-1, 0)))
(top ++ bottom ++ left ++ right).map(countEnergized(grid, _)).max
(top ++ bottom ++ left ++ right).map(countEnergized0(grid)).tapEach(println).max
}


Expand Down
19 changes: 6 additions & 13 deletions src/test/scala/eu/sim642/adventofcode2023/Day16Test.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,23 @@ import org.scalatest.funsuite.AnyFunSuite
class Day16Test extends AnyFunSuite {

private val exampleInput =
""".|...\....
||.-.\.....
|.....|-...
|........|.
|..........
|.........\
|..../.\\..
|.-.-/..|..
|.|....-|.\
|..//.|....""".stripMargin
""".\.
|.-\
|.\/""".stripMargin

test("Part 1 examples") {
assert(countEnergized(parseGrid(exampleInput)) == 46)
}

test("Part 1 input answer") {
assert(countEnergized(parseGrid(input)) == 7067)
//assert(countEnergized(parseGrid(input)) == 7067)
}

test("Part 2 examples") {
assert(maxEnergized(parseGrid(exampleInput)) == 51)
//assert(maxEnergized(parseGrid(exampleInput)) == 51)
}

test("Part 2 input answer") {
assert(maxEnergized(parseGrid(input)) == 7324)
//assert(maxEnergized(parseGrid(input)) == 7324)
}
}

0 comments on commit eab4c00

Please sign in to comment.