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);
        }
Beispiel #2
0
        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);
        }
Beispiel #5
0
        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);
        }
Beispiel #6
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);
        }
Beispiel #7
0
 public Machine(BootProgram program) => _program = program;