From 3b20909ed15e7e67d35aaf1d13acad116713fc50 Mon Sep 17 00:00:00 2001 From: kamoshi <18511281+kamoshi@users.noreply.github.com> Date: Mon, 9 Dec 2019 11:08:57 +0100 Subject: [PATCH] Add files via upload --- 2019/Scala/day09/Day09.scala | 20 +++++ 2019/Scala/day09/Main.scala | 20 +++++ 2019/Scala/day09/intcode/Machine.scala | 78 +++++++++++++++++++ 2019/Scala/day09/intcode/opcode/Action.scala | 7 ++ 2019/Scala/day09/intcode/opcode/Input.scala | 7 ++ 2019/Scala/day09/intcode/opcode/Jump.scala | 8 ++ 2019/Scala/day09/intcode/opcode/OpCode.scala | 60 ++++++++++++++ 2019/Scala/day09/intcode/opcode/OpCode1.scala | 15 ++++ 2019/Scala/day09/intcode/opcode/OpCode2.scala | 15 ++++ 2019/Scala/day09/intcode/opcode/OpCode3.scala | 14 ++++ 2019/Scala/day09/intcode/opcode/OpCode4.scala | 14 ++++ 2019/Scala/day09/intcode/opcode/OpCode5.scala | 14 ++++ 2019/Scala/day09/intcode/opcode/OpCode6.scala | 14 ++++ 2019/Scala/day09/intcode/opcode/OpCode7.scala | 16 ++++ 2019/Scala/day09/intcode/opcode/OpCode8.scala | 16 ++++ 2019/Scala/day09/intcode/opcode/OpCode9.scala | 13 ++++ .../Scala/day09/intcode/opcode/OpCode99.scala | 6 ++ 2019/Scala/day09/intcode/opcode/Output.scala | 7 ++ 18 files changed, 344 insertions(+) create mode 100644 2019/Scala/day09/Day09.scala create mode 100644 2019/Scala/day09/Main.scala create mode 100644 2019/Scala/day09/intcode/Machine.scala create mode 100644 2019/Scala/day09/intcode/opcode/Action.scala create mode 100644 2019/Scala/day09/intcode/opcode/Input.scala create mode 100644 2019/Scala/day09/intcode/opcode/Jump.scala create mode 100644 2019/Scala/day09/intcode/opcode/OpCode.scala create mode 100644 2019/Scala/day09/intcode/opcode/OpCode1.scala create mode 100644 2019/Scala/day09/intcode/opcode/OpCode2.scala create mode 100644 2019/Scala/day09/intcode/opcode/OpCode3.scala create mode 100644 2019/Scala/day09/intcode/opcode/OpCode4.scala create mode 100644 2019/Scala/day09/intcode/opcode/OpCode5.scala create mode 100644 2019/Scala/day09/intcode/opcode/OpCode6.scala create mode 100644 2019/Scala/day09/intcode/opcode/OpCode7.scala create mode 100644 2019/Scala/day09/intcode/opcode/OpCode8.scala create mode 100644 2019/Scala/day09/intcode/opcode/OpCode9.scala create mode 100644 2019/Scala/day09/intcode/opcode/OpCode99.scala create mode 100644 2019/Scala/day09/intcode/opcode/Output.scala diff --git a/2019/Scala/day09/Day09.scala b/2019/Scala/day09/Day09.scala new file mode 100644 index 0000000..83a11ad --- /dev/null +++ b/2019/Scala/day09/Day09.scala @@ -0,0 +1,20 @@ +package day09 + +import day09.intcode.Machine + +class Day09(original: Array[Long]) +{ + def solveP1(): Long = + { + val machine = new Machine(original) + machine.runUntilIO().runInput(1) + machine.runUntilIO().runOutput() + } + + def solveP2(): Long = + { + val machine = new Machine(original) + machine.runUntilIO().runInput(2) + machine.runUntilIO().runOutput() + } +} diff --git a/2019/Scala/day09/Main.scala b/2019/Scala/day09/Main.scala new file mode 100644 index 0000000..bc3250b --- /dev/null +++ b/2019/Scala/day09/Main.scala @@ -0,0 +1,20 @@ +package day09 + +import kamlib.{Reader, Wrapper} + +object Main { + + def main(args: Array[String]): Unit = + { + // Initialize initial program memory + 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 solution: Day09 = new Day09(memory) + + println("Part 1:") + Wrapper(solution.solveP1()).print() + println("Part 2:") + Wrapper(solution.solveP2()).print() + } +} diff --git a/2019/Scala/day09/intcode/Machine.scala b/2019/Scala/day09/intcode/Machine.scala new file mode 100644 index 0000000..e3b7177 --- /dev/null +++ b/2019/Scala/day09/intcode/Machine.scala @@ -0,0 +1,78 @@ +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") + } + } +} diff --git a/2019/Scala/day09/intcode/opcode/Action.scala b/2019/Scala/day09/intcode/opcode/Action.scala new file mode 100644 index 0000000..f6887cd --- /dev/null +++ b/2019/Scala/day09/intcode/opcode/Action.scala @@ -0,0 +1,7 @@ +package day09.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) +} diff --git a/2019/Scala/day09/intcode/opcode/Input.scala b/2019/Scala/day09/intcode/opcode/Input.scala new file mode 100644 index 0000000..383fc03 --- /dev/null +++ b/2019/Scala/day09/intcode/opcode/Input.scala @@ -0,0 +1,7 @@ +package day09.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 +} diff --git a/2019/Scala/day09/intcode/opcode/Jump.scala b/2019/Scala/day09/intcode/opcode/Jump.scala new file mode 100644 index 0000000..6ead36e --- /dev/null +++ b/2019/Scala/day09/intcode/opcode/Jump.scala @@ -0,0 +1,8 @@ +package day09.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) +} + diff --git a/2019/Scala/day09/intcode/opcode/OpCode.scala b/2019/Scala/day09/intcode/opcode/OpCode.scala new file mode 100644 index 0000000..9d60945 --- /dev/null +++ b/2019/Scala/day09/intcode/opcode/OpCode.scala @@ -0,0 +1,60 @@ +package day09.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) + } + } +} diff --git a/2019/Scala/day09/intcode/opcode/OpCode1.scala b/2019/Scala/day09/intcode/opcode/OpCode1.scala new file mode 100644 index 0000000..3b1bf96 --- /dev/null +++ b/2019/Scala/day09/intcode/opcode/OpCode1.scala @@ -0,0 +1,15 @@ +package day09.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) + } +} diff --git a/2019/Scala/day09/intcode/opcode/OpCode2.scala b/2019/Scala/day09/intcode/opcode/OpCode2.scala new file mode 100644 index 0000000..fa32c8f --- /dev/null +++ b/2019/Scala/day09/intcode/opcode/OpCode2.scala @@ -0,0 +1,15 @@ +package day09.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 + } +} diff --git a/2019/Scala/day09/intcode/opcode/OpCode3.scala b/2019/Scala/day09/intcode/opcode/OpCode3.scala new file mode 100644 index 0000000..d214a89 --- /dev/null +++ b/2019/Scala/day09/intcode/opcode/OpCode3.scala @@ -0,0 +1,14 @@ +package day09.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) + } +} diff --git a/2019/Scala/day09/intcode/opcode/OpCode4.scala b/2019/Scala/day09/intcode/opcode/OpCode4.scala new file mode 100644 index 0000000..1863715 --- /dev/null +++ b/2019/Scala/day09/intcode/opcode/OpCode4.scala @@ -0,0 +1,14 @@ +package day09.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) + } +} diff --git a/2019/Scala/day09/intcode/opcode/OpCode5.scala b/2019/Scala/day09/intcode/opcode/OpCode5.scala new file mode 100644 index 0000000..fdd4a59 --- /dev/null +++ b/2019/Scala/day09/intcode/opcode/OpCode5.scala @@ -0,0 +1,14 @@ +package day09.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) + } +} diff --git a/2019/Scala/day09/intcode/opcode/OpCode6.scala b/2019/Scala/day09/intcode/opcode/OpCode6.scala new file mode 100644 index 0000000..ba68ee4 --- /dev/null +++ b/2019/Scala/day09/intcode/opcode/OpCode6.scala @@ -0,0 +1,14 @@ +package day09.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) + } +} diff --git a/2019/Scala/day09/intcode/opcode/OpCode7.scala b/2019/Scala/day09/intcode/opcode/OpCode7.scala new file mode 100644 index 0000000..c234211 --- /dev/null +++ b/2019/Scala/day09/intcode/opcode/OpCode7.scala @@ -0,0 +1,16 @@ +package day09.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) + } +} diff --git a/2019/Scala/day09/intcode/opcode/OpCode8.scala b/2019/Scala/day09/intcode/opcode/OpCode8.scala new file mode 100644 index 0000000..c7f1e07 --- /dev/null +++ b/2019/Scala/day09/intcode/opcode/OpCode8.scala @@ -0,0 +1,16 @@ +package day09.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) + } +} diff --git a/2019/Scala/day09/intcode/opcode/OpCode9.scala b/2019/Scala/day09/intcode/opcode/OpCode9.scala new file mode 100644 index 0000000..e366b7b --- /dev/null +++ b/2019/Scala/day09/intcode/opcode/OpCode9.scala @@ -0,0 +1,13 @@ +package day09.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 +} diff --git a/2019/Scala/day09/intcode/opcode/OpCode99.scala b/2019/Scala/day09/intcode/opcode/OpCode99.scala new file mode 100644 index 0000000..bdfe52b --- /dev/null +++ b/2019/Scala/day09/intcode/opcode/OpCode99.scala @@ -0,0 +1,6 @@ +package day09.intcode.opcode + +case object OpCode99 extends OpCode { + /** length of an instruction */ + override val length: Int = 1 +} diff --git a/2019/Scala/day09/intcode/opcode/Output.scala b/2019/Scala/day09/intcode/opcode/Output.scala new file mode 100644 index 0000000..d88f9d7 --- /dev/null +++ b/2019/Scala/day09/intcode/opcode/Output.scala @@ -0,0 +1,7 @@ +package day09.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 +}