static int NextIfFlipped(Machine m) { var instr = m.Program[m.PC]; var flipped = InstructionFactory.Flip(instr); int pc = m.PC; int ac = 0; flipped.Execute(ref pc, ref ac); return(pc); }
static int SolveAlternate() { var machine = new Machine(TextFile.ReadStringList("input.txt")); var target = machine.Program.Count; var originalRun = machine.RunFrom(0); foreach (var i in originalRun) { var originalInstruction = machine.Program[i]; var flippedInstruction = InstructionFactory.Flip(originalInstruction); machine.Program[i] = flippedInstruction; var visited = machine.RunFrom(i); if (visited.Contains(target)) { machine.AC = 0; machine.PC = 0; machine.RunFrom(0); return(machine.AC); } machine.Program[i] = originalInstruction; } return(-1); }
static void Main(string[] args) { int acWithoutFlip = 0; int acAfterFlip = 0; Performance.TimeRun("Read and solve", () => { var machine = new Machine(TextFile.ReadStringList("input.txt")); var visited = machine.RunFrom(0); acWithoutFlip = machine.AC; var target = machine.Program.Count; HashSet <int> knownGood = new HashSet <int>(); HashSet <int> knownBad = new HashSet <int>(visited); for (int i = 1; i < machine.Program.Count; i++) { if (knownBad.Contains(i) || knownGood.Contains(i))//this instruction has already been visited in a previous path { continue; } visited = machine.RunFrom(i); if (visited.Contains(target)) { knownGood.UnionWith(visited); } else { knownBad.UnionWith(visited); } } machine.AC = 0; machine.PC = 0; bool flipped = false; while (machine.PC < machine.Program.Count) { if (!flipped) { var candidate = NextIfFlipped(machine); if (knownGood.Contains(candidate)) //flipping this instructions brings us to a "winning" path { var curr = machine.Program[machine.PC]; var flippedInstruction = InstructionFactory.Flip(curr); machine.Program[machine.PC] = flippedInstruction; flipped = true; } } machine.Step(); } acAfterFlip = machine.AC; }, 100, 10); Performance.TimeRun("Alternate solve", () => { acAfterFlip = SolveAlternate(); }, 100, 10); Console.WriteLine($"AC before flip: {acWithoutFlip}"); Console.WriteLine($"AC after flip: {acAfterFlip}"); }