public Span <int> Run(int input) { var programSpan = program.AsSpan(); var instructionPointer = 0; while (true) { var opCodeText = programSpan[instructionPointer].ToString(); var paramModeRepository = ParameterModeRepository.ParseFromOpCode(opCodeText); var extractor = new ParameterExtractor(paramModeRepository); var parsedOpCode = opCodeText.Length > 1 ? int.Parse(opCodeText.Substring(opCodeText.Length - 2, 2)) : programSpan[instructionPointer]; switch (parsedOpCode) { case 1: Operation(programSpan, instructionPointer, (a, b) => a + b, extractor); instructionPointer += 4; break; case 2: Operation(programSpan, instructionPointer, (a, b) => a * b, extractor); instructionPointer += 4; break; case 3: programSpan[programSpan[instructionPointer + 1]] = input; instructionPointer += 2; break; case 4: var outputValue = extractor.GetParameterValue(programSpan, 0, instructionPointer); Console.WriteLine(outputValue); instructionPointer += 2; break; case 5: JumpToWhenTrue(programSpan, ref instructionPointer, extractor, v => v != 0); break; case 6: JumpToWhenTrue(programSpan, ref instructionPointer, extractor, v => v == 0); break; case 7: WriteTrueIfTrueAt(programSpan, ref instructionPointer, extractor, (a, b) => a < b); break; case 8: WriteTrueIfTrueAt(programSpan, ref instructionPointer, extractor, (a, b) => a == b); break; case 99: return(programSpan); } } }
private static void Operation(Span <int> program, int instructionPointer, Func <int, int, int> operation, ParameterExtractor extractor) { var arg1 = extractor.GetParameterValue(program, 0, instructionPointer); var arg2 = extractor.GetParameterValue(program, 1, instructionPointer); var resultPosition = program[instructionPointer + 3]; program[resultPosition] = operation(arg1, arg2); }
private static void JumpToWhenTrue(Span <int> programSpan, ref int instructionPointer, ParameterExtractor extractor, Func <int, bool> predicate) { var testValue = extractor.GetParameterValue(programSpan, 0, instructionPointer); if (predicate(testValue)) { instructionPointer = extractor.GetParameterValue(programSpan, 1, instructionPointer); } else { instructionPointer += 3; } }
private static void WriteTrueIfTrueAt(Span <int> programSpan, ref int instructionPointer, ParameterExtractor extractor, Func <int, int, bool> predicate) { var arg1 = extractor.GetParameterValue(programSpan, 0, instructionPointer); var arg2 = extractor.GetParameterValue(programSpan, 1, instructionPointer); var writeToPointer = instructionPointer + 3; programSpan[programSpan[writeToPointer]] = predicate(arg1, arg2) ? 1 : 0; instructionPointer += 4; }