Add files via upload

This commit is contained in:
kamoshi 2019-12-09 13:20:04 +01:00 committed by GitHub
parent 3b20909ed1
commit 2187baf229
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 436 additions and 0 deletions

View file

@ -0,0 +1,139 @@
package intcode
import intcode.opcode.{Action, Input, Jump, OpCode9, OpCode99, Output}
/**
* Virtual IntCode machine
* @param input Memory used to initialize the machine with.
*/
class Machine(input: Array[Long])
{
private[this] val original: Array[Long] = input.clone() // original memory saved in case of reset
private[this] var software: Array[Long] = input.clone() // working memory used by the machine
private[this] var pointer: Int = 0 // instruction pointer
private[this] var relative: Long = 0 // relative pointer
private[this] var state: State = Ready // machine state
def isHalted: Boolean = state != Ready
def isIO: Boolean = state == Input || state == Output
def isReady: Boolean = state == Ready
def isInput: Boolean = state == Input
def isOutput: Boolean = state == Output
def getState: State = state
def getMem(ptr: Int): Long =
software(ptr)
def setMem(ptr: Int, value: Long): Unit =
software(ptr) = value
def reset(): Machine =
{
software = original.clone()
state = Ready
pointer = 0
this
}
@scala.annotation.tailrec
final def run(): Machine =
{
val tuple = OpCode99.parseInt(software(pointer).toInt)
tuple match
{
case (_, _, _, OpCode99) =>
state = Finished
this
case (_, _, _, outputInstr: Output) =>
state = Output
this
case (_, _, _, inputInstr: Input) =>
state = 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
state = Ready
run()
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
state = Ready
run()
case (_, _, m1, OpCode9) =>
relative += OpCode9.exec(software, relative, software(pointer+1), m1)
pointer += OpCode9.length
state = Ready
run()
case _ => throw new Exception("Something went wrong")
}
}
def runInput(input: Long): Machine =
{
val tuple = OpCode99.parseInt(software(pointer).toInt)
tuple match
{
case (_, _, _, OpCode99) =>
state = Finished
this
case (_, _, m1, inputInstr: Input) =>
inputInstr.input(software, relative, software(pointer+1), m1, input)
pointer += inputInstr.length
state = Ready
this
case _ => throw new Exception("Unexpected instruction")
}
}
def runOutput(): Long =
{
val tuple = OpCode99.parseInt(software(pointer).toInt)
tuple match
{
case (_, _, _, OpCode99) =>
state = Finished
0
case (_, _, m1, outputInstr: Output) =>
val out = outputInstr.output(software, relative, software(pointer+1), m1)
pointer += outputInstr.length
state = Ready
out
case _ => throw new Exception("Unexpected instruction")
}
}
@scala.annotation.tailrec
final def runContinuous(inputs: List[Long], outputs: List[Long] = List()): List[Long] =
{
this.state match
{
case Ready =>
run()
runContinuous(inputs, outputs)
case Finished =>
outputs
case Output =>
runContinuous(inputs, this.runOutput()::outputs)
case Input =>
if (inputs.isEmpty)
{
println("Ran out of inputs")
outputs
}
else
{
runInput(inputs.head)
runContinuous(inputs.tail, outputs)
}
}
}
}

View file

@ -0,0 +1,48 @@
package intcode
import kamlib.Reader
object MachineTest
{
def testDay02(): Unit =
{
val input: Array[Long] = Reader.readString("/input2.txt").split("[^\\d-]+").map(x => x.toLong)
val machine1: Machine = new Machine(input)
machine1.setMem(1, 12)
machine1.setMem(2,2)
assert(machine1.run().getMem(0) == 9706670)
val machine2: Machine = new Machine(input)
machine2.setMem(1, 25)
machine2.setMem(2, 52)
assert(machine2.run().getMem(0) == 19690720)
}
def testDay05(): Unit =
{
val input: Array[Long] = Reader.readString("/input5.txt").split("[^\\d-]+").map(x => x.toLong)
val machine1: Machine = new Machine(input)
assert(machine1.runContinuous(List(1)).head == 12234644)
val machine2: Machine = new Machine(input)
assert(machine2.run().runInput(5).run().runOutput() == 3508186)
}
def testDay09(): Unit =
{
val memory: Array[Long] = Array.ofDim[Long](1200)
val input: Array[Long] = Reader.readString("/input9.txt").split("[^\\d-]+").map(x => x.toLong)
for(i <- input.indices) { memory(i) = input(i)}
val machine1: Machine = new Machine(memory)
machine1.run().runInput(1)
assert(machine1.run().runOutput() == 4288078517L)
val machine2: Machine = new Machine(memory)
machine2.run().runInput(2)
assert(machine2.run().runOutput() == 69256)
}
}

View file

@ -0,0 +1,13 @@
package intcode
object Main {
def main(args: Array[String]): Unit =
{
println("Running tests")
MachineTest.testDay02()
MachineTest.testDay05()
MachineTest.testDay09()
println("Test finished")
}
}

View file

@ -0,0 +1,7 @@
package intcode
sealed trait State
case object Ready extends State
case object Input extends State
case object Output extends State
case object Finished extends State

View file

@ -0,0 +1,7 @@
package intcode.opcode
trait Action extends OpCode
{
/** Executes instruction for given parameters and modes */
def exec(tape: Array[Long], relative: Long, param1: Long, param2: Long, param3: Long, mode1: Int, mode2: Int, mode3: Int)
}

View file

@ -0,0 +1,7 @@
package intcode.opcode
trait Input extends OpCode
{
/** Executes instruction for given parameters and modes */
def input(tape: Array[Long], relative: Long, param1: Long, mode1: Int, input: Long): Unit
}

View file

@ -0,0 +1,8 @@
package intcode.opcode
trait Jump extends OpCode
{
/** Checks if the condition for jumping is fulfilled, returns boolean and jump pointer */
def checkConditionAndJump(tape: Array[Long], relative: Long, param1: Long, param2: Long, param3: Long, mode1: Int, mode2: Int, mode3: Int): (Boolean, Int)
}

View file

@ -0,0 +1,60 @@
package intcode.opcode
trait OpCode
{
/** length of an instruction */
val length: Int
/** Parse int to full OpCode */
def parseInt(code: Int): (Int, Int, Int, OpCode) = // Dunno how to make this static lmao
{
val opCodeInt: Int = code % 100 // Instruction Code
val modeStr = code.toString.substring(0, {if (code.toString.length > 1) code.toString.length - 2 else 0})
val modes = "000".substring(modeStr.length) + modeStr
(modes(0).asDigit, modes(1).asDigit, modes(2).asDigit, opCodeInt) match
{
case (a, b, c, 1) => (a, b, c, OpCode1)
case (a, b, c, 2) => (a, b, c, OpCode2)
case (a, b, c, 3) => (a, b, c, OpCode3)
case (a, b, c, 4) => (a, b, c, OpCode4)
case (a, b, c, 5) => (a, b, c, OpCode5)
case (a, b, c, 6) => (a, b, c, OpCode6)
case (a, b, c, 7) => (a, b, c, OpCode7)
case (a, b, c, 8) => (a, b, c, OpCode8)
case (a, b, c, 9) => (a, b, c, OpCode9)
case (_, _, _, 99) => (0, 0, 0, OpCode99)
case c => throw new Exception("Wrong instruction code " + c)
}
}
/** Returns correct value, immediate or positional */
protected[this] def accessor(relative: Long, param: Long, mode: Int, tape: Array[Long]): Long =
{
mode match
{
case 0 => /* println("Reading "+tape(param)+" from array("+param+")");*/ tape(param.toInt)
case 1 => /*println("Reading "+param+" immediate");*/ param
case 2 => tape((param+relative).toInt)
case p => throw new Exception("HCF: wrong accessor parameter " + p)
}
}
/**
* Writes something to the tape
* @param tape Program memory
* @param relative Relative index
* @param param Location where to write
* @param mode Where to write: 0->tape(param1); 2->tape(param1+relative)
* @param value What to write to the tape
*/
protected[this] def writer(tape: Array[Long], relative: Long, param: Long, mode: Int, value: Long): Unit =
{
mode match
{
case 0 => tape(param.toInt) = value//; println("Writing "+value+" to array("+param+")")
case 1 => throw new Exception("HCF: unimplemented writer parameter 1")
case 2 => tape((param+relative).toInt) = value
case p => throw new Exception("HCF: wrong writer parameter " + p)
}
}
}

View file

@ -0,0 +1,15 @@
package intcode.opcode
/** Sum */
case object OpCode1 extends Action
{
/** length of an instruction */
override val length: Int = 4
/** Executes instruction for given parameters and modes */
override def exec(tape: Array[Long], relative: Long, param1: Long, param2: Long, param3: Long, mode1: Int, mode2: Int, mode3: Int): Unit =
{
val result = accessor(relative, param1, mode1, tape) + accessor(relative, param2, mode2, tape)
writer(tape, relative, param3, mode3, result)
}
}

View file

@ -0,0 +1,15 @@
package intcode.opcode
/** Multiplication */
case object OpCode2 extends Action
{
/** length of an instruction */
override val length: Int = 4
/** Executes instruction for given parameters and modes */
override def exec(tape: Array[Long], relative: Long, param1: Long, param2: Long, param3: Long, mode1: Int, mode2: Int, mode3: Int): Unit =
{
val result = accessor(relative, param1, mode1, tape) * accessor(relative, param2, mode2, tape)
writer(tape, relative, param3, mode3, result) // Write mode is 0 default for now
}
}

View file

@ -0,0 +1,14 @@
package intcode.opcode
/** Input */
case object OpCode3 extends Input
{
/** length of an instruction */
override val length: Int = 2
/** Executes instruction for given parameters and modes */
override def input(tape: Array[Long], relative: Long, param1: Long, mode1: Int, input: Long): Unit =
{
writer(tape, relative, param1, mode1, input)
}
}

View file

@ -0,0 +1,14 @@
package intcode.opcode
/** Output */
case object OpCode4 extends Output
{
/** length of an instruction */
override val length: Int = 2
/** Executes instruction for given parameters and modes */
override def output(tape: Array[Long], relative: Long, param1: Long, mode1: Int): Long =
{
accessor(relative, param1, mode1, tape)
}
}

View file

@ -0,0 +1,14 @@
package intcode.opcode
case object OpCode5 extends Jump
{
/** length of an instruction */
override val length: Int = 3
/** Executes instruction for given parameters and modes */
override def checkConditionAndJump(tape: Array[Long], relative: Long, param1: Long, param2: Long, param3: Long, mode1: Int, mode2: Int, mode3: Int): (Boolean, Int) =
{
if (accessor(relative, param1, mode1, tape) != 0) (true, accessor(relative, param2, mode2, tape).toInt)
else (false, 0)
}
}

View file

@ -0,0 +1,14 @@
package intcode.opcode
case object OpCode6 extends Jump
{
/** length of an instruction */
override val length: Int = 3
/** Executes instruction for given parameters and modes */
override def checkConditionAndJump(tape: Array[Long], relative: Long, param1: Long, param2: Long, param3: Long, mode1: Int, mode2: Int, mode3: Int): (Boolean, Int) =
{
if (accessor(relative, param1, mode1, tape) == 0) (true, accessor(relative, param2, mode2, tape).toInt)
else (false, 0)
}
}

View file

@ -0,0 +1,16 @@
package intcode.opcode
case object OpCode7 extends Action
{
/** length of an instruction */
override val length: Int = 4
/** Executes instruction for given parameters and modes */
override def exec(tape: Array[Long], relative: Long, param1: Long, param2: Long, param3: Long, mode1: Int, mode2: Int, mode3: Int): Unit =
{
if (accessor(relative, param1, mode1, tape) < accessor(relative, param2, mode2, tape))
writer(tape, relative, param3, mode3, 1)
else
writer(tape, relative, param3, mode3, 0)
}
}

View file

@ -0,0 +1,16 @@
package intcode.opcode
case object OpCode8 extends Action
{
/** length of an instruction */
override val length: Int = 4
/** Executes instruction for given parameters and modes */
override def exec(tape: Array[Long], relative: Long, param1: Long, param2: Long, param3: Long, mode1: Int, mode2: Int, mode3: Int): Unit =
{
if (accessor(relative, param1, mode1, tape) == accessor(relative, param2, mode2, tape))
writer(tape, relative, param3, mode3, 1)
else
writer(tape, relative, param3, mode3, 0)
}
}

View file

@ -0,0 +1,13 @@
package intcode.opcode
case object OpCode9 extends OpCode
{
/** Find what to add to relative */
def exec(tape: Array[Long], relative: Long, param1: Long, mode1: Int): Long =
{
accessor(relative, param1, mode1, tape)
}
/** length of an instruction */
override val length: Int = 2
}

View file

@ -0,0 +1,6 @@
package intcode.opcode
case object OpCode99 extends OpCode {
/** length of an instruction */
override val length: Int = 1
}

View file

@ -0,0 +1,7 @@
package intcode.opcode
trait Output extends OpCode
{
/** Executes instruction for given parameters and modes */
def output(tape: Array[Long], relative: Long, param1: Long, mode1: Int): Long
}

View file

@ -0,0 +1 @@
1,0,0,3,1,1,2,3,1,3,4,3,1,5,0,3,2,10,1,19,1,5,19,23,1,23,5,27,2,27,10,31,1,5,31,35,2,35,6,39,1,6,39,43,2,13,43,47,2,9,47,51,1,6,51,55,1,55,9,59,2,6,59,63,1,5,63,67,2,67,13,71,1,9,71,75,1,75,9,79,2,79,10,83,1,6,83,87,1,5,87,91,1,6,91,95,1,95,13,99,1,10,99,103,2,6,103,107,1,107,5,111,1,111,13,115,1,115,13,119,1,13,119,123,2,123,13,127,1,127,6,131,1,131,9,135,1,5,135,139,2,139,6,143,2,6,143,147,1,5,147,151,1,151,2,155,1,9,155,0,99,2,14,0,0

View file

@ -0,0 +1 @@
3,225,1,225,6,6,1100,1,238,225,104,0,1002,43,69,224,101,-483,224,224,4,224,1002,223,8,223,1001,224,5,224,1,224,223,223,1101,67,60,225,1102,5,59,225,1101,7,16,225,1102,49,72,225,101,93,39,224,101,-98,224,224,4,224,102,8,223,223,1001,224,6,224,1,224,223,223,1102,35,82,225,2,166,36,224,101,-4260,224,224,4,224,102,8,223,223,101,5,224,224,1,223,224,223,102,66,48,224,1001,224,-4752,224,4,224,102,8,223,223,1001,224,2,224,1,223,224,223,1001,73,20,224,1001,224,-55,224,4,224,102,8,223,223,101,7,224,224,1,223,224,223,1102,18,41,224,1001,224,-738,224,4,224,102,8,223,223,101,6,224,224,1,224,223,223,1101,68,71,225,1102,5,66,225,1101,27,5,225,1101,54,63,224,1001,224,-117,224,4,224,102,8,223,223,1001,224,2,224,1,223,224,223,1,170,174,224,101,-71,224,224,4,224,1002,223,8,223,1001,224,4,224,1,223,224,223,4,223,99,0,0,0,677,0,0,0,0,0,0,0,0,0,0,0,1105,0,99999,1105,227,247,1105,1,99999,1005,227,99999,1005,0,256,1105,1,99999,1106,227,99999,1106,0,265,1105,1,99999,1006,0,99999,1006,227,274,1105,1,99999,1105,1,280,1105,1,99999,1,225,225,225,1101,294,0,0,105,1,0,1105,1,99999,1106,0,300,1105,1,99999,1,225,225,225,1101,314,0,0,106,0,0,1105,1,99999,1007,226,226,224,1002,223,2,223,1006,224,329,1001,223,1,223,1007,226,677,224,102,2,223,223,1006,224,344,1001,223,1,223,108,677,677,224,102,2,223,223,1005,224,359,1001,223,1,223,1007,677,677,224,1002,223,2,223,1006,224,374,101,1,223,223,8,677,226,224,1002,223,2,223,1006,224,389,101,1,223,223,7,226,226,224,1002,223,2,223,1005,224,404,101,1,223,223,7,677,226,224,102,2,223,223,1005,224,419,1001,223,1,223,8,226,677,224,1002,223,2,223,1005,224,434,101,1,223,223,1008,226,677,224,102,2,223,223,1006,224,449,1001,223,1,223,7,226,677,224,1002,223,2,223,1006,224,464,1001,223,1,223,108,677,226,224,102,2,223,223,1005,224,479,101,1,223,223,108,226,226,224,1002,223,2,223,1006,224,494,101,1,223,223,8,226,226,224,1002,223,2,223,1005,224,509,1001,223,1,223,1107,677,226,224,102,2,223,223,1005,224,524,1001,223,1,223,1107,226,226,224,102,2,223,223,1005,224,539,1001,223,1,223,1108,677,677,224,1002,223,2,223,1006,224,554,101,1,223,223,107,226,677,224,102,2,223,223,1005,224,569,1001,223,1,223,1108,226,677,224,1002,223,2,223,1005,224,584,1001,223,1,223,1107,226,677,224,1002,223,2,223,1005,224,599,1001,223,1,223,1008,226,226,224,1002,223,2,223,1005,224,614,101,1,223,223,107,226,226,224,102,2,223,223,1006,224,629,1001,223,1,223,1008,677,677,224,1002,223,2,223,1006,224,644,101,1,223,223,107,677,677,224,1002,223,2,223,1005,224,659,101,1,223,223,1108,677,226,224,1002,223,2,223,1006,224,674,1001,223,1,223,4,223,99,226

View file

@ -0,0 +1 @@
1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1102,1,3,1000,109,988,209,12,9,1000,209,6,209,3,203,0,1008,1000,1,63,1005,63,65,1008,1000,2,63,1005,63,902,1008,1000,0,63,1005,63,58,4,25,104,0,99,4,0,104,0,99,4,17,104,0,99,0,0,1101,0,39,1005,1102,1,1,1021,1101,0,212,1025,1101,0,24,1014,1102,22,1,1019,1101,0,35,1003,1101,38,0,1002,1101,0,571,1026,1102,32,1,1006,1102,31,1,1000,1102,25,1,1018,1102,1,37,1016,1101,0,820,1023,1102,1,29,1004,1101,564,0,1027,1101,0,375,1028,1101,26,0,1013,1102,1,370,1029,1101,21,0,1007,1101,0,0,1020,1102,1,30,1001,1102,36,1,1011,1102,1,27,1017,1101,0,28,1012,1101,0,217,1024,1101,823,0,1022,1102,1,20,1009,1101,0,23,1010,1101,34,0,1015,1101,33,0,1008,109,5,1208,0,39,63,1005,63,199,4,187,1106,0,203,1001,64,1,64,1002,64,2,64,109,13,2105,1,6,4,209,1105,1,221,1001,64,1,64,1002,64,2,64,109,-4,21108,40,39,-1,1005,1013,241,1001,64,1,64,1105,1,243,4,227,1002,64,2,64,109,5,21102,41,1,-1,1008,1018,40,63,1005,63,267,1001,64,1,64,1106,0,269,4,249,1002,64,2,64,109,-28,1202,10,1,63,1008,63,30,63,1005,63,291,4,275,1106,0,295,1001,64,1,64,1002,64,2,64,109,24,21107,42,43,-4,1005,1011,313,4,301,1106,0,317,1001,64,1,64,1002,64,2,64,109,-8,21108,43,43,3,1005,1010,335,4,323,1105,1,339,1001,64,1,64,1002,64,2,64,109,-8,1207,4,34,63,1005,63,359,1001,64,1,64,1106,0,361,4,345,1002,64,2,64,109,26,2106,0,3,4,367,1106,0,379,1001,64,1,64,1002,64,2,64,109,-21,2102,1,-2,63,1008,63,37,63,1005,63,399,1105,1,405,4,385,1001,64,1,64,1002,64,2,64,109,2,1207,-2,30,63,1005,63,427,4,411,1001,64,1,64,1105,1,427,1002,64,2,64,109,4,2108,36,-5,63,1005,63,447,1001,64,1,64,1106,0,449,4,433,1002,64,2,64,109,-13,1201,8,0,63,1008,63,41,63,1005,63,469,1106,0,475,4,455,1001,64,1,64,1002,64,2,64,109,14,21107,44,43,3,1005,1014,495,1001,64,1,64,1106,0,497,4,481,1002,64,2,64,109,2,1205,8,511,4,503,1106,0,515,1001,64,1,64,1002,64,2,64,109,14,1206,-6,527,1105,1,533,4,521,1001,64,1,64,1002,64,2,64,109,-29,2107,31,8,63,1005,63,551,4,539,1105,1,555,1001,64,1,64,1002,64,2,64,109,28,2106,0,1,1001,64,1,64,1106,0,573,4,561,1002,64,2,64,109,-3,21101,45,0,-4,1008,1019,45,63,1005,63,595,4,579,1105,1,599,1001,64,1,64,1002,64,2,64,109,-23,1208,2,39,63,1005,63,615,1105,1,621,4,605,1001,64,1,64,1002,64,2,64,109,15,2108,32,-9,63,1005,63,643,4,627,1001,64,1,64,1105,1,643,1002,64,2,64,109,-9,2107,33,0,63,1005,63,659,1106,0,665,4,649,1001,64,1,64,1002,64,2,64,109,7,21101,46,0,2,1008,1015,49,63,1005,63,689,1001,64,1,64,1106,0,691,4,671,1002,64,2,64,109,-8,2101,0,-3,63,1008,63,35,63,1005,63,711,1105,1,717,4,697,1001,64,1,64,1002,64,2,64,109,12,1202,-9,1,63,1008,63,31,63,1005,63,741,1001,64,1,64,1105,1,743,4,723,1002,64,2,64,109,-27,2102,1,10,63,1008,63,31,63,1005,63,769,4,749,1001,64,1,64,1105,1,769,1002,64,2,64,109,9,2101,0,1,63,1008,63,31,63,1005,63,791,4,775,1106,0,795,1001,64,1,64,1002,64,2,64,109,28,1206,-7,809,4,801,1105,1,813,1001,64,1,64,1002,64,2,64,2105,1,-4,1106,0,829,4,817,1001,64,1,64,1002,64,2,64,109,-15,21102,47,1,-2,1008,1010,47,63,1005,63,851,4,835,1106,0,855,1001,64,1,64,1002,64,2,64,109,5,1205,3,867,1106,0,873,4,861,1001,64,1,64,1002,64,2,64,109,-12,1201,0,0,63,1008,63,39,63,1005,63,895,4,879,1105,1,899,1001,64,1,64,4,64,99,21101,0,27,1,21102,913,1,0,1106,0,920,21201,1,47951,1,204,1,99,109,3,1207,-2,3,63,1005,63,962,21201,-2,-1,1,21101,0,940,0,1105,1,920,21201,1,0,-1,21201,-2,-3,1,21101,0,955,0,1106,0,920,22201,1,-1,-2,1105,1,966,21202,-2,1,-2,109,-3,2105,1,0