Skip to content

Commit

Permalink
Clean up 2023 day 20
Browse files Browse the repository at this point in the history
  • Loading branch information
sim642 committed Dec 20, 2023
1 parent d422bfe commit 6ee7f6a
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 51 deletions.
86 changes: 38 additions & 48 deletions src/main/scala/eu/sim642/adventofcode2023/Day20.scala
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package eu.sim642.adventofcode2023

import eu.sim642.adventofcodelib.IteratorImplicits.*
import eu.sim642.adventofcodelib.NumberTheory
import eu.sim642.adventofcodelib.IteratorImplicits._

import scala.collection.{View, mutable}
import scala.collection.mutable

object Day20 {

Expand All @@ -23,7 +23,7 @@ object Day20 {
}
}

case class Conjunction(remember: Map[String, Pulse] = Map.empty) extends Module { // TODO: add initial Lows
case class Conjunction(remember: Map[String, Pulse] = Map.empty) extends Module {
override def handle(from: String, pulse: Pulse): (Module, Option[Pulse]) = {
val newRemember = remember.updated(from, pulse)
val outPulse = if (newRemember.forall(_._2 == Pulse.High)) Pulse.Low else Pulse.High
Expand All @@ -41,77 +41,67 @@ object Day20 {
inputs: Map[String, Set[String]]) {

def simulate(): (Circuit, Seq[(String, Pulse, String)]) = {
val mCircuit = modules.to(mutable.Map)
val b = Seq.newBuilder[(String, Pulse, String)]
val currentModules = modules.to(mutable.Map)
val pulses = Seq.newBuilder[(String, Pulse, String)]

val queue = mutable.Queue.empty[(String, Pulse, String)]
queue.enqueue(("button", Pulse.Low, "broadcaster"))

while (queue.nonEmpty) {
val s@(from, pulse, to) = queue.dequeue()
//println(s)
b += s
val pulseTriple@(from, pulse, to) = queue.dequeue()
pulses += pulseTriple

mCircuit.get(to) match {
currentModules.get(to) match {
case None => () // output
case Some(module) =>
val outputs = this.outputs(to)
val toOutputs = outputs(to)
val (newModule, outPulse) = module.handle(from, pulse)
mCircuit(to) = newModule
currentModules(to) = newModule

for {
pulse <- outPulse
output <- outputs
} queue.enqueue((to, pulse, output))
toOutput <- toOutputs
} queue.enqueue((to, pulse, toOutput))
}
}

val newCircuit = copy(modules = mCircuit.toMap)
(newCircuit, b.result())
val newCircuit = copy(modules = currentModules.toMap)
(newCircuit, pulses.result())
}
}

def countPulses(circuit: Circuit): Int = {
var mCircuit = circuit
def countLowHigh(initialCircuit: Circuit): Int = {
var circuit = initialCircuit
val pulseCount = mutable.Map.empty[Pulse, Int].withDefaultValue(0)

var lowPulses = 0
var highPulses = 0
for (_ <- 0 until 1000) {
val (newCircuit, pulses) = circuit.simulate()
circuit = newCircuit

for (i <- 0 until 1000) {
val (mCircuit2, pulses) = mCircuit.simulate()
mCircuit = mCircuit2

for ((_, pulse, _) <- pulses) {
pulse match {
case Pulse.Low => lowPulses += 1
case Pulse.High => highPulses += 1
}
}
for ((_, pulse, _) <- pulses)
pulseCount(pulse) += 1
}

lowPulses * highPulses
pulseCount.values.product
}

def countRx(circuit: Circuit): Long = {
val ms = circuit.inputs(circuit.inputs("rx").head)

var mCircuit = circuit

var presses = 0

def countRx(initialCircuit: Circuit): Long = {
var circuit = initialCircuit
val rxInputs = circuit.inputs("rx")
assert(rxInputs.size == 1)
val todo = circuit.inputs(rxInputs.head).to(mutable.Set)
assert(todo.size == 4)
val found = mutable.Map.empty[String, Int]

while (found.size < ms.size) {
val (mCircuit2, pulses) = mCircuit.simulate()
mCircuit = mCircuit2
presses += 1
var i = 0
while (todo.nonEmpty) {
val (newCircuit, pulses) = circuit.simulate()
circuit = newCircuit
i += 1

for (pulse <- pulses) {
pulse match {
case (from, Pulse.High, to) if ms(from) =>
found(from) = presses
case _ => ()
}
for (case (from, Pulse.High, _) <- pulses if todo(from)) {
todo -= from
found(from) = i
}
}

Expand Down Expand Up @@ -162,7 +152,7 @@ object Day20 {

def main(args: Array[String]): Unit = {
val circuit = parseCircuit(input)
println(countPulses(circuit))
println(countLowHigh(circuit))
//printCircuitDot(circuit)
println(countRx(circuit))
}
Expand Down
6 changes: 3 additions & 3 deletions src/test/scala/eu/sim642/adventofcode2023/Day20Test.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ class Day20Test extends AnyFunSuite {
|&con -> output""".stripMargin

test("Part 1 examples") {
assert(countPulses(parseCircuit(exampleInput)) == 32000000)
assert(countPulses(parseCircuit(exampleInput2)) == 11687500)
assert(countLowHigh(parseCircuit(exampleInput)) == 32000000)
assert(countLowHigh(parseCircuit(exampleInput2)) == 11687500)
}

test("Part 1 input answer") {
assert(countPulses(parseCircuit(input)) == 867118762)
assert(countLowHigh(parseCircuit(input)) == 867118762)
}

test("Part 2 input answer") {
Expand Down

0 comments on commit 6ee7f6a

Please sign in to comment.