private static BootProgram ReadProgram(List <string> lines) { var program = new BootProgram(); foreach (var line in lines) { var instruction = ReadInstruction(line); program.Instructions.Add(instruction); } return(program); }
public static long Part1(BootProgram program) { if (program == null) { throw new ArgumentNullException(nameof(program)); } var machine = new Machine(program); machine.Run(); return(machine.Acc); }
private static bool ExecuteProgram(BootProgram program) { // Reset execution state foreach (var instruction in program.Instructions) { instruction.IsExecuted = false; } program.State.Accumulator = 0; var ip = 0; var instructions = program.Instructions; var state = program.State; while (ip < instructions.Count) { var instruction = instructions[ip]; if (instruction.IsExecuted) { return(false); // we stop but didn't finish } instruction.IsExecuted = true; switch (instruction.Operation) { case "nop": { ip++; break; } case "acc": { state.Accumulator += instruction.Argument; ip++; break; } case "jmp": { ip += instruction.Argument; break; } default: throw new Exception($"Unpexpected instruction: {instruction.Operation}"); } } return(true); }
private static bool PatchProgram(BootProgram program, int patchIndex) { // Only works after executing once, we find the latest executed jmp instruction and patch to nop var lastInstruction = program.Instructions.AsEnumerable()?.Skip(patchIndex).FirstOrDefault(i => i.Operation == "jmp" || i.Operation == "nop"); if (lastInstruction == null) { throw new Exception($"Found no more instructions to patch (patched {patchIndex + 1}"); } // Patch and check if we finish now PatchOperation(lastInstruction); var result = ExecuteProgram(program); PatchOperation(lastInstruction); // Patch it back, so the next run gets a clean app return(result); }
public static int Main(string[] args) { if (args == null) { throw new ArgumentNullException(nameof(args)); } string filename = args.Length > 0 ? args[0] : "input.txt"; if (!File.Exists(filename)) { Console.Error.WriteLine($"File not found: {filename}"); return(100); } BootProgram program = BootProgram.FromString(File.ReadAllText(filename)); Console.WriteLine(Solver.Part1(program)); Console.WriteLine(Solver.Part2(program)); return(0); }
public static long Part2(BootProgram program) { if (program == null) { throw new ArgumentNullException(nameof(program)); } var machine = new Machine(program); int ptrPatch = -1; while (!machine.Run()) { // Patch program var patchedProgram = new BootProgram(program.Instructions); while (true) { ptrPatch += 1; Instruction instruction = patchedProgram.Instructions[ptrPatch]; if (instruction.OpCode == OpCode.Jmp) { patchedProgram.Patch(ptrPatch, new Instruction(OpCode.Nop, instruction.Arg)); break; } else if (instruction.OpCode == OpCode.Nop) { patchedProgram.Patch(ptrPatch, new Instruction(OpCode.Jmp, instruction.Arg)); break; } } // Initialize new machine with patched program machine = new Machine(patchedProgram); } return(machine.Acc); }
public Machine(BootProgram program) => _program = program;