advent-of-code/2019/Scala/day09/intcode/Machine.scala

79 lines
2.4 KiB
Scala
Raw Normal View History

2019-12-09 11:08:57 +01:00
package day09.intcode
import day09.intcode.opcode.{Action, Input, Jump, OpCode9, OpCode99, Output}
class Machine(input: Array[Long])
{
private[this] val original = input.clone()
private[this] var software = input.clone()
private[this] var pointer = 0
private[this] var relative: Long = 0
private[this] var halted = false
def isHalted: Boolean = halted
def reset(): Machine = {
software = original.clone()
halted = false
pointer = 0
this
}
@scala.annotation.tailrec
final def runUntilIO(): Machine =
{
val tuple = OpCode99.parseInt(software(pointer).toInt);
tuple match
{
case (_, _, _, OpCode99) =>
halted = true
this
case (_, _, _, outputInstr: Output) => this
case (_, _, _, inputInstr: Input) => this
case (m3, m2, m1, instruction: Jump) =>
val (bool, jmpPtr) = instruction.checkConditionAndJump(software, relative, software(pointer+1), software(pointer+2), software(pointer+3), m1, m2, m3)
if (bool) pointer = jmpPtr
else pointer += instruction.length
runUntilIO()
case (m3, m2, m1, instruction: Action) =>
instruction.exec(software, relative, software(pointer+1), software(pointer+2), software(pointer+3), m1, m2, m3)
pointer += instruction.length
runUntilIO()
case (_, _, m1, OpCode9) =>
relative += OpCode9.exec(software, relative, software(pointer+1), m1)
pointer += OpCode9.length
runUntilIO()
case _ => throw new Exception("Something went wrong")
}
}
def runInput(input: Long): Machine =
{
val tuple = OpCode99.parseInt(software(pointer).toInt)
tuple match
{
case (_, _, _, OpCode99) => this
case (_, _, m1, inputInstr: Input) =>
inputInstr.input(software, relative, software(pointer+1), m1, input)
pointer += inputInstr.length
this
case _ => throw new Exception("Unexpected instruction")
}
}
def runOutput(): Long =
{
val tuple = OpCode99.parseInt(software(pointer).toInt)
tuple match
{
case (_, _, _, OpCode99) => 0
case (_, _, m1, outputInstr: Output) =>
val out = outputInstr.output(software, relative, software(pointer+1), m1)
pointer += outputInstr.length
out
case _ => throw new Exception("Unexpected instruction")
}
}
}