public void Run() { while (_iPointer >= 0 && _iPointer < Memory.Length) { var instruction = Memory[_iPointer]; var opCode = instruction % 100; switch (opCode) { case 1: Add(); break; case 2: Multiply(); break; case 3: if (!InputQueue.Any()) { return; } ReadInput(); break; case 4: WriteOutput(); break; case 5: JumpIfTrue(); break; case 6: JumpIfFalse(); break; case 7: LessThan(); break; case 8: Equals(); break; case 99: Halted = true; return; default: throw new Exception($"Unexpected opcode: {opCode}"); } } }
public bool AwaitingInput() { return(PeekNext() == 3 && !InputQueue.Any()); }
public long RunNext() { string fullOpcode = Memory[InstructionPtr].ToString().PadLeft(5, '0'); long opcode = long.Parse(fullOpcode.Substring(3, 2)); long param1Mode = long.Parse(fullOpcode.Substring(2, 1)); long param2Mode = long.Parse(fullOpcode.Substring(1, 1)); long param3Mode = long.Parse(fullOpcode.Substring(0, 1)); long param1 = 0; long param2 = 0; long param3 = 0; long param1Key = 0; long param2Key = 0; long param3Key = 0; if (new long[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }.Contains(opcode)) { if (!Memory.ContainsKey(InstructionPtr + 1)) { Memory.Add(InstructionPtr + 1, 0); } switch (param1Mode) { case 0: param1Key = Memory[InstructionPtr + 1]; if (!Memory.ContainsKey(param1Key)) { Memory.Add(param1Key, 0); } param1 = Memory[param1Key]; break; case 1: param1 = Memory[InstructionPtr + 1]; break; case 2: param1Key = RelativeBase + Memory[InstructionPtr + 1]; if (!Memory.ContainsKey(param1Key)) { Memory.Add(param1Key, 0); } param1 = Memory[param1Key]; break; } } if (new long[] { 1, 2, 5, 6, 7, 8 }.Contains(opcode)) { if (!Memory.ContainsKey(InstructionPtr + 2)) { Memory.Add(InstructionPtr + 2, 0); } switch (param2Mode) { case 0: param2Key = Memory[InstructionPtr + 2]; if (!Memory.ContainsKey(param2Key)) { Memory.Add(param2Key, 0); } param2 = Memory[param2Key]; break; case 1: param2 = Memory[InstructionPtr + 2]; break; case 2: param2Key = RelativeBase + Memory[InstructionPtr + 2]; if (!Memory.ContainsKey(param2Key)) { Memory.Add(param2Key, 0); } param2 = Memory[param2Key]; break; } } if (new long[] { 1, 2, 7, 8 }.Contains(opcode)) { if (!Memory.ContainsKey(InstructionPtr + 3)) { Memory.Add(InstructionPtr + 3, 0); } switch (param3Mode) { case 0: param3Key = Memory[InstructionPtr + 3]; if (!Memory.ContainsKey(param3Key)) { Memory.Add(param3Key, 0); } param3 = Memory[param3Key]; break; case 1: param3 = Memory[InstructionPtr + 3]; break; case 2: param3Key = RelativeBase + Memory[InstructionPtr + 3]; if (!Memory.ContainsKey(param3Key)) { Memory.Add(param3Key, 0); } param3 = Memory[param3Key]; break; } } switch (opcode) { case 1: Memory[param3Key] = param1 + param2; InstructionPtr += 4; break; case 2: Memory[param3Key] = param1 * param2; InstructionPtr += 4; break; case 3: bool success = false; long parsed = long.MinValue; while (!success) { string input; if (InputQueue.Any()) { input = InputQueue.Dequeue().ToString(); if (PrintOutput) { Console.WriteLine($"Input: {input}"); } } else if (AsciiInputMode) { string line = Console.ReadLine(); AddAsciiInput(line + "\n"); input = ""; } else { Console.Write("Input: "); input = Console.ReadLine(); } success = long.TryParse(input.Trim(), out parsed); } Memory[param1Key] = parsed; InstructionPtr += 2; break; case 4: if (PrintOutput) { Console.WriteLine($"Output: {param1}"); } OutputQueue.Enqueue(param1); InstructionPtr += 2; break; case 5: if (param1 != 0) { InstructionPtr = param2; } else { InstructionPtr += 3; } break; case 6: if (param1 == 0) { InstructionPtr = param2; } else { InstructionPtr += 3; } break; case 7: Memory[param3Key] = param1 < param2 ? 1 : 0; InstructionPtr += 4; break; case 8: Memory[param3Key] = param1 == param2 ? 1 : 0; InstructionPtr += 4; break; case 9: RelativeBase += param1; InstructionPtr += 2; break; case 99: return(Memory[0]); default: throw new Exception($"Unknown opcode: {opcode} at {InstructionPtr}"); } return(long.MinValue); }
//public Queue<long> Compute() public void Compute() { long pc = 0; //program counter long rb = 0; //relative base while (pc < memory.Length) { var instruction = memory[pc].ToString("00000"); long opcode = int.Parse(instruction.Substring(instruction.Length - 2)); char p1Mode = instruction[2]; char p2Mode = instruction[1]; char p3Mode = instruction[0]; if (opcode == 99) { //halt break; } else if (opcode == 1) { //add SetParameter(pc + 3, p3Mode, rb, GetParameter(pc + 1, p1Mode, rb) + GetParameter(pc + 2, p2Mode, rb)); pc += 4; } else if (opcode == 2) { //mult SetParameter(pc + 3, p3Mode, rb, GetParameter(pc + 1, p1Mode, rb) * GetParameter(pc + 2, p2Mode, rb)); pc += 4; } else if (opcode == 3) { //read input from inputQueue bool spinlock = true; while (spinlock) { lock (InputQueue){ if (InputQueue.Any()) { SetParameter(pc + 1, p1Mode, rb, InputQueue.Dequeue()); spinlock = false; } } } pc += 2; } else if (opcode == 4) { //write output var output = GetParameter(pc + 1, p1Mode, rb); if (OutputToConsole) { Console.WriteLine(output); } lock (OutputQueue) { OutputQueue.Enqueue(output); } pc += 2; } else if (opcode == 5) { //jump if true if (GetParameter(pc + 1, p1Mode, rb) != 0) { pc = GetParameter(pc + 2, p2Mode, rb); } else { pc += 3; } } else if (opcode == 6) { //jump if false if (GetParameter(pc + 1, p1Mode, rb) == 0) { pc = GetParameter(pc + 2, p2Mode, rb); } else { pc += 3; } } else if (opcode == 7) { //less than if (GetParameter(pc + 1, p1Mode, rb) < GetParameter(pc + 2, p2Mode, rb)) { SetParameter(pc + 3, p3Mode, rb, 1); } else { SetParameter(pc + 3, p3Mode, rb, 0); } pc += 4; } else if (opcode == 8) { //equals if (GetParameter(pc + 1, p1Mode, rb) == GetParameter(pc + 2, p2Mode, rb)) { SetParameter(pc + 3, p3Mode, rb, 1); } else { SetParameter(pc + 3, p3Mode, rb, 0); } pc += 4; } else if (opcode == 9) { rb += GetParameter(pc + 1, p1Mode, rb); pc += 2; } else { Console.WriteLine("ERR!!!!!"); } } //return OutputQueue; }