// Flips exactly one(1) instruction from Nop->Jmp or Jmp->Nop so the program can run all the way through. // Prints the accumulator after that. // Correct answer: 1703 public int SolutionPart2() { // list of all indices of Instructions that can be reached if starting from the last instruction and working backwards List <int> vmReversed = InstructionMethods.BackTravelFromIndex(allInstructions, allInstructions.Count - 1); int accumulator = 0; // VM should run from the top int currentIndex = 0; // Current instruction in the loop and a tempInstruction used for switching Instruction currInstr; Instruction tempInstr = null; // if the switch is found, no reason to test anymore bool switchFound = false; // Program should stop when the index reaches the end while (currentIndex != allInstructions.Count) { currInstr = allInstructions[currentIndex]; // test for Instruction type and makes a temp swapped version of it. if (!switchFound) { if (currInstr is Nop) { tempInstr = InstructionMethods.SwapType <Jmp>(currInstr); } else if (currInstr is Jmp) { tempInstr = InstructionMethods.SwapType <Nop>(currInstr); } } // if the next index of the swapped instruction is in the vmreversed list - // then the switch will cause the program to complete if (tempInstr != null && vmReversed.Contains(tempInstr.NextIndex)) { // current instruction is set to the swapped currInstr = tempInstr; switchFound = true; } // current instruction runs its action against index and accumulator currInstr.Action(ref currentIndex, ref accumulator); // the temp instruction is removed tempInstr = null; } return(accumulator); }
// // From a List of Instructions and a Index, travels backwards and makes a list of all instructions visited that way. public static List <int> BackTravelFromIndex(List <Instruction> instructions, int fromIndex) { // Uses Graph traversal logic - the list of instructions never change. List <int> visitedInstructions = new List <int>(); Instruction currInstr = instructions[fromIndex]; // always add current index to the list visitedInstructions.Add(currInstr.Index); // returns from here, if no instructions leads to the current instruction if (currInstr.FormerIndices.Count == 0) { return(visitedInstructions); } foreach (int index in currInstr.FormerIndices) { visitedInstructions.AddRange(InstructionMethods.BackTravelFromIndex(instructions, index)); } return(visitedInstructions); }