71 lines
2.4 KiB
Scala
71 lines
2.4 KiB
Scala
package aoc.y2019
|
|
|
|
import aoc.Day
|
|
import aoc.y2019.intcode.Machine
|
|
import cats._
|
|
import cats.implicits._
|
|
|
|
import scala.annotation.tailrec
|
|
|
|
object Day07 extends Day {
|
|
|
|
@tailrec def runAmplifiers(machine: Machine, order: Seq[Int], input: BigInt = 0): BigInt = {
|
|
if(order.isEmpty) {
|
|
input
|
|
} else {
|
|
val firstInput = order.head
|
|
val secondInput = input
|
|
val runAmplifier = for {
|
|
_ <- Machine.input(firstInput)
|
|
_ <- Machine.input(secondInput)
|
|
ran <- Machine.run()
|
|
} yield ran
|
|
val output = runAmplifier.runS(machine).value.output.head
|
|
runAmplifiers(machine, order.tail, output)
|
|
}
|
|
}
|
|
|
|
override def part1(input: String): String = {
|
|
val memory = input.split(",").map(BigInt(_)).toVector
|
|
val initialState = Machine(memory)
|
|
val maximumSignal = (0 to 4).permutations.map(runAmplifiers(initialState, _)).max
|
|
maximumSignal.toString
|
|
}
|
|
|
|
def loopAmplifiers(base: Machine, initialInputs: Seq[Int]): BigInt = {
|
|
val numAmplifiers = initialInputs.size
|
|
val initialMachines = Vector.fill(numAmplifiers)(base).zip(initialInputs).map {
|
|
case (machine, phase) => machine.copy(input = machine.input :+ phase)
|
|
}
|
|
val haltCondition = for {
|
|
waitingForInput <- Machine.waitingForInput
|
|
isHalted <- Machine.isHalted
|
|
} yield waitingForInput || isHalted
|
|
val runToNextMachine = Machine.run(haltCondition = haltCondition)
|
|
@tailrec def go(index: Int, machines: Vector[Machine], lastOutput: BigInt = 0): Vector[Machine] = {
|
|
if(machines.traverse(machine => Machine.isHalted.runA(machine)).value.forall(identity)) machines
|
|
else {
|
|
val thisMachine = machines(index)
|
|
val inputAndRun = for {
|
|
inputLastOutput <- Machine.input(lastOutput)
|
|
runAsFarAsPossible<- runToNextMachine
|
|
} yield runAsFarAsPossible
|
|
val ranMachine = inputAndRun.runS(thisMachine).value
|
|
val nextOutput = ranMachine.output.last
|
|
val nextIndex = (index + 1) % machines.size
|
|
val nextMachines = machines.updated(index, ranMachine)
|
|
go(nextIndex, nextMachines, nextOutput)
|
|
}
|
|
}
|
|
go(0, initialMachines).last.output.last
|
|
}
|
|
|
|
override def part2(input: String): String = {
|
|
val memory = input.split(",").map(BigInt(_)).toVector
|
|
val initialState = Machine(memory)
|
|
val maximumSignal = (5 to 9).permutations.map(loopAmplifiers(initialState, _)).max
|
|
maximumSignal.toString
|
|
}
|
|
|
|
}
|