public static BootCode ParseInputLines(IList <string> inputLines) { var bootCodeInstructions = new List <BootCodeInstruction>(); foreach (var inputLine in inputLines) { var instruction = ParseBootCodeInstruction(inputLine); bootCodeInstructions.Add(instruction); } var result = new BootCode(bootCodeInstructions); return(result); }
public static bool TryFindFixedProgram(BootCode originalBootCode, out BootCode fixedBootCode, out int accumulator) { fixedBootCode = null; accumulator = 0; var possiblyFixedBootCodes = GetPossiblyFixedBootCodes(originalBootCode); foreach (var possiblyFixedBootCode in possiblyFixedBootCodes) { var isSuccessfulTermination = TryRunProgram(possiblyFixedBootCode, out int possibleAccumulator); if (isSuccessfulTermination) { fixedBootCode = possiblyFixedBootCode; accumulator = possibleAccumulator; return(true); } } return(false); }
public static IList <BootCode> GetPossiblyFixedBootCodes(BootCode bootCode) { var result = new List <BootCode>(); for (int i = 0; i < bootCode.Instructions.Count; i++) { var currentInstruction = bootCode.Instructions[i]; if ("jmp".Equals(currentInstruction.Instruction) || "nop".Equals(currentInstruction.Instruction)) { var instructionsCopy = bootCode.Instructions.ToList(); var newInstruction = "jmp".Equals(currentInstruction.Instruction) ? "nop" : "jmp"; instructionsCopy[i] = new BootCodeInstruction(newInstruction, currentInstruction.Value); var newBootCode = new BootCode(instructionsCopy); result.Add(newBootCode); } } return(result); }
/// <summary> /// Runs the given boot code program. /// Returns true if the program terminates correctly. /// Otherwise, returns false. /// </summary> /// <param name="bootCode"></param> /// <param name="accumulator"></param> /// <returns></returns> public static bool TryRunProgram(BootCode bootCode, out int accumulator) { accumulator = 0; var instructionsExecuted = new HashSet <int>(); var currentInstructionIndex = 0; while (!instructionsExecuted.Contains(currentInstructionIndex)) { instructionsExecuted.Add(currentInstructionIndex); if (currentInstructionIndex == bootCode.Instructions.Count) { // Terminate when trying to execute the instruction immediately after the last one return(true); } if (currentInstructionIndex < 0 || currentInstructionIndex > bootCode.Instructions.Count) { throw new Exception($"Instruction index out of range - Current index: {currentInstructionIndex}, # Instructions: {bootCode.Instructions.Count}"); } var instruction = bootCode.Instructions[currentInstructionIndex]; if ("acc".Equals(instruction.Instruction)) { accumulator += instruction.Value; currentInstructionIndex++; } else if ("jmp".Equals(instruction.Instruction)) { currentInstructionIndex += instruction.Value; } else if ("nop".Equals(instruction.Instruction)) { currentInstructionIndex++; } else { throw new Exception($"Invalid instruction: {instruction.Instruction}"); } } return(false); }