private long GetInput() { if (Inputs.Count == 0 && DefaultInput.HasValue) { return(DefaultInput.Value); } return(Inputs.Dequeue()); }
private long GetNextInput() { while (!Exited) { lock (InputLock) { if (Inputs.Count > 0) { Paused = false; return(Inputs.Dequeue()); } else if (DefaultInput.HasValue) { return(DefaultInput.Value); } } Paused = true; Thread.Sleep(1); } throw new InterruptedWhileAwaitingInputError(); }
private long[] GetParams(long instruction, int PC, Operation op) { long[] res; Mode[] modes = GetModes((int)(instruction / 100)); long immediate; switch (op) { case Operation.Add: case Operation.Multiply: case Operation.LessThan: case Operation.TestEquals: res = new long[3]; //Let's just assume that any operation can take 3 params except reading input (must wait for input) and Halting for (int i = 0; i < 3; i++) { try { immediate = (int)WorkingProgram[PC + i + 1]; if (modes[i] == Mode.Position && i != 2) //If it's the output location, we still need teh "immediate" value { res[i] = WorkingProgram[(int)immediate]; } else if (modes[i] == Mode.Relative) { if (i == 2) { res[i] = (int)immediate + RelativeBase; } else { res[i] = WorkingProgram[(int)immediate + RelativeBase]; } } else if (modes[i] == Mode.Immediate || i == 2) { res[i] = immediate; } else { throw new Exception("Something broke"); } } catch (IndexOutOfRangeException) { res[i] = 0; } } break; case Operation.WriteOutput: res = new long[1]; immediate = WorkingProgram[PC + 1]; if (modes[0] == Mode.Position) { res[0] = WorkingProgram[(int)immediate]; } else if (modes[0] == Mode.Immediate) { res[0] = immediate; } else { res[0] = WorkingProgram[(int)immediate + RelativeBase]; } break; case Operation.RelativeBaseAdjust: res = new long[1]; //Let's just assume that any operation can take 3 params except reading input (must wait for input) and Halting immediate = WorkingProgram[PC + 1]; if (modes[0] == Mode.Position) { res[0] = WorkingProgram[(int)immediate]; } else if (modes[0] == Mode.Immediate) { res[0] = immediate; } else { res[0] = WorkingProgram[(int)immediate + RelativeBase]; } break; case Operation.JumpTrue: case Operation.JumpFalse: res = new long[2]; for (int i = 0; i < 2; i++) { try { immediate = (int)WorkingProgram[PC + i + 1]; if (modes[i] == Mode.Position) { res[i] = WorkingProgram[(int)immediate]; } else if (modes[i] == Mode.Immediate) { res[i] = immediate; } else { res[i] = WorkingProgram[(int)immediate + RelativeBase]; } } catch (IndexOutOfRangeException) { res[i] = 0; } } break; case Operation.ReadInput: res = new long[2]; int QL = 0; do { lock (Inputs) { QL = Inputs.Count; } } while (QL == 0); lock (Inputs) { res[0] = Inputs.Dequeue(); } immediate = (int)WorkingProgram[PC + 1]; if (modes[0] == Mode.Relative) { res[1] = (int)immediate + RelativeBase; } else { res[1] = immediate; } break; case Operation.HALT: return(null); default: throw new Exception("Not a valid Opcode"); } return(res); }
public void RunIntCode(BreakMode breakMode = BreakMode.Output) { while (!IsHalted) { ExecutedInstructions++; var instruction = _intCode[_instructionPointer].ToString().PadLeft(5, '0'); var opCode = (OpCode)(GetNumber(instruction[3]) * 10 + GetNumber(instruction[4])); var modeParam1 = (Mode)GetNumber(instruction[2]); var modeParam2 = (Mode)GetNumber(instruction[1]); var modeParam3 = (Mode)GetNumber(instruction[0]); switch (opCode) { case OpCode.Sum: { var param1Value = GetParamValue(modeParam1, _instructionPointer + 1); var param2Value = GetParamValue(modeParam2, _instructionPointer + 2); var value = param1Value + param2Value; WriteMem(modeParam3, _instructionPointer + 3, value); _instructionPointer += 4; break; } case OpCode.Multiply: { var param1Value = GetParamValue(modeParam1, _instructionPointer + 1); var param2Value = GetParamValue(modeParam2, _instructionPointer + 2); var value = param1Value * param2Value; WriteMem(modeParam3, _instructionPointer + 3, value); _instructionPointer += 4; break; } case OpCode.Input: { if (breakMode == BreakMode.Input && Inputs.Count == 0) { return; } WriteMem(modeParam1, _instructionPointer + 1, Inputs.Dequeue()); _instructionPointer += 2; break; } case OpCode.Output: { var param2Value = GetParamValue(modeParam1, _instructionPointer + 1); Output.Enqueue(param2Value); _instructionPointer += 2; if (breakMode == BreakMode.Output) { return; } break; } case OpCode.JumpIfTrue: { var param1Value = GetParamValue(modeParam1, _instructionPointer + 1); var param2Value = GetParamValue(modeParam2, _instructionPointer + 2); _instructionPointer = param1Value != 0 ? param2Value : _instructionPointer + 3; break; } case OpCode.JumpIfFalse: { var param1Value = GetParamValue(modeParam1, _instructionPointer + 1); var param2Value = GetParamValue(modeParam2, _instructionPointer + 2); _instructionPointer = param1Value == 0 ? param2Value : _instructionPointer + 3; break; } case OpCode.LessThan: { var param1Value = GetParamValue(modeParam1, _instructionPointer + 1); var param2Value = GetParamValue(modeParam2, _instructionPointer + 2); WriteMem(modeParam3, _instructionPointer + 3, param1Value < param2Value ? 1 : 0); _instructionPointer += 4; break; } case OpCode.Equals: { var param1Value = GetParamValue(modeParam1, _instructionPointer + 1); var param2Value = GetParamValue(modeParam2, _instructionPointer + 2); WriteMem(modeParam3, _instructionPointer + 3, param1Value == param2Value ? 1 : 0); _instructionPointer += 4; break; } case OpCode.RelativeBaseOffset: { var param1Value = GetParamValue(modeParam1, _instructionPointer + 1); _relativeBase += param1Value; _instructionPointer += 2; break; } case OpCode.Halt: IsHalted = true; break; default: throw new ArgumentOutOfRangeException($"!Unknown OpCode {opCode}!"); } } }
public void ProcessOpCodes(int[] opCodes) { for (var i = 0; i < opCodes.Length; i++) { var op = opCodes[i]; if (op == 99) { break; } var modeP1 = 0; var modeP2 = 0; var modeP3 = 0; if (op > 99) { var ops = op.ToString().PadLeft(5, '0'); modeP3 = int.Parse(ops.Substring(0, 1)); modeP2 = int.Parse(ops.Substring(1, 1)); modeP1 = int.Parse(ops.Substring(2, 1)); var newOp = ops.Substring(3); // update the opcode op = int.Parse(newOp); } if (op == 1) { var source1 = opCodes[++i]; var source2 = opCodes[++i]; var target = opCodes[++i]; var val1 = (modeP1 == 1) ? source1 : opCodes[source1]; var val2 = (modeP2 == 1) ? source2 : opCodes[source2]; opCodes[target] = val1 + val2; } else if (op == 2) { var source1 = opCodes[++i]; var source2 = opCodes[++i]; var target = opCodes[++i]; var val1 = (modeP1 == 1) ? source1 : opCodes[source1]; var val2 = (modeP2 == 1) ? source2 : opCodes[source2]; opCodes[target] = val1 * val2; } else if (op == 3) { var target = opCodes[++i]; opCodes[target] = Inputs.Dequeue(); } else if (op == 4) { var target = opCodes[++i]; var val1 = (modeP1 == 1) ? target : opCodes[target]; Output = val1; } else if (op == 5) { // jump if true var source1 = opCodes[++i]; var source2 = opCodes[++i]; var val1 = (modeP1 == 1) ? source1 : opCodes[source1]; var val2 = (modeP2 == 1) ? source2 : opCodes[source2]; if (val1 > 0) { i = val2 - 1; // +1 gets added on loop. continue; } } else if (op == 6) { // jump if false var source1 = opCodes[++i]; var source2 = opCodes[++i]; var val1 = (modeP1 == 1) ? source1 : opCodes[source1]; var val2 = (modeP2 == 1) ? source2 : opCodes[source2]; if (val1 == 0) { i = val2 - 1; // +1 gets added on loop continue; } } else if (op == 7) { // less than var source1 = opCodes[++i]; var source2 = opCodes[++i]; var target = opCodes[++i]; var val1 = (modeP1 == 1) ? source1 : opCodes[source1]; var val2 = (modeP2 == 1) ? source2 : opCodes[source2]; opCodes[target] = (val1 < val2) ? 1 : 0; } else if (op == 8) { // equals var source1 = opCodes[++i]; var source2 = opCodes[++i]; var target = opCodes[++i]; var val1 = (modeP1 == 1) ? source1 : opCodes[source1]; var val2 = (modeP2 == 1) ? source2 : opCodes[source2]; opCodes[target] = (val1 == val2) ? 1 : 0; } else { throw new Exception("invalid op"); } } }
private int GetInput() => Inputs.Dequeue();
private int ReadInput() { return(Inputs.Dequeue()); }
public ExitCode Run() { try { int opcode = 0; while (opcode != 99) { opcode = (int)(Instructions[PC]) % 100; int p1mode = (int)((Instructions[PC] / 100) % 10); int p2mode = (int)((Instructions[PC] / 1000) % 10); int p3mode = (int)((Instructions[PC] / 10000) % 10); BigInteger GetValue(int m, BigInteger v, int mode = 0) { BigInteger a = 0; if (mode == 0) { switch (m) { case 0: a = Instructions[(int)v]; break; case 1: a = v; break; case 2: a = Instructions[(int)v + RelativeBase]; break; } } else { switch (m) { case 0: a = v; break; case 1: a = v; break; case 2: a = (int)v + RelativeBase; break; } } return(a); } switch (opcode) { case 1: Instructions[(int)GetValue(p3mode, Instructions[PC + 3], 1)] = GetValue(p1mode, Instructions[PC + 1]) + GetValue(p2mode, Instructions[PC + 2]); PC += 4; break; case 2: Instructions[(int)GetValue(p3mode, Instructions[PC + 3], 1)] = GetValue(p1mode, Instructions[PC + 1]) * GetValue(p2mode, Instructions[PC + 2]); PC += 4; break; case 3: if (Inputs.Any()) { Instructions[(int)GetValue(p1mode, Instructions[PC + 1], 1)] = Inputs.Dequeue(); PC += 2; } else { return(ExitCode.NEED_INPUT); } break; case 4: Outputs.Enqueue(GetValue(p1mode, Instructions[PC + 1])); PC += 2; break; case 5: PC = (int)(GetValue(p1mode, Instructions[PC + 1]) != 0 ? GetValue(p2mode, Instructions[PC + 2]) : (PC + 3)); break; case 6: PC = (int)(GetValue(p1mode, Instructions[PC + 1]) == 0 ? GetValue(p2mode, Instructions[PC + 2]) : (PC + 3)); break; case 7: Instructions[(int)GetValue(p3mode, Instructions[PC + 3], 1)] = GetValue(p1mode, Instructions[PC + 1]) < GetValue(p2mode, Instructions[PC + 2]) ? 1 : 0; PC += 4; break; case 8: Instructions[(int)GetValue(p3mode, Instructions[PC + 3], 1)] = GetValue(p1mode, Instructions[PC + 1]) == GetValue(p2mode, Instructions[PC + 2]) ? 1 : 0; PC += 4; break; case 9: RelativeBase += (int)GetValue(p1mode, Instructions[PC + 1]); PC += 2; break; case 99: break; } } } catch (Exception) { Console.WriteLine("Invalid Program"); return(ExitCode.EXCEPTION); } return(ExitCode.HALT); }
public ExitCode Run() { try { int opcode = 0; while (opcode != 99) { opcode = Instructions[PC] % 100; var p1mode = (Instructions[PC] / 100) % 10; var p2mode = (Instructions[PC] / 1000) % 10; var p3mode = (Instructions[PC] / 10000) % 10; int GetValue(int m, int v) => m != 0 ? v : Instructions[v]; switch (opcode) { case 1: Instructions[Instructions[PC + 3]] = GetValue(p1mode, Instructions[PC + 1]) + GetValue(p2mode, Instructions[PC + 2]); PC += 4; break; case 2: Instructions[Instructions[PC + 3]] = GetValue(p1mode, Instructions[PC + 1]) * GetValue(p2mode, Instructions[PC + 2]); PC += 4; break; case 3: if (Inputs.Count() > 0) { Instructions[Instructions[PC + 1]] = Inputs.Dequeue(); PC += 2; } else { return(ExitCode.NEED_INPUT); } break; case 4: Outputs.Enqueue(GetValue(p1mode, Instructions[PC + 1])); //Console.WriteLine($"Enqueued {Outputs.Peek()}"); PC += 2; break; case 5: PC = GetValue(p1mode, Instructions[PC + 1]) != 0 ? GetValue(p2mode, Instructions[PC + 2]) : (PC + 3); break; case 6: PC = GetValue(p1mode, Instructions[PC + 1]) == 0 ? GetValue(p2mode, Instructions[PC + 2]) : (PC + 3); break; case 7: Instructions[Instructions[PC + 3]] = GetValue(p1mode, Instructions[PC + 1]) < GetValue(p2mode, Instructions[PC + 2]) ? 1 : 0; PC += 4; break; case 8: Instructions[Instructions[PC + 3]] = GetValue(p1mode, Instructions[PC + 1]) == GetValue(p2mode, Instructions[PC + 2]) ? 1 : 0; PC += 4; break; case 99: break; } } } catch (Exception) { Console.WriteLine("Invalid Program"); return(ExitCode.EXCEPTION); } return(ExitCode.HALT); }