Advertisement
eltea

Advent of Code Day 08 Parts 1 and 2

Dec 10th, 2020 (edited)
239
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 4.01 KB | None | 0 0
  1. //Advent of Code 2020 Day 8 Parts 1 and 2 solution by Mike LeSauvage
  2. public class ProgramEvaluator : MonoBehaviour
  3. {
  4.     [SerializeField] TextAsset instructions = null; //Hooked up in the input text in the Unity editor.
  5.  
  6.     // Start is a Unity method called once per program execution.
  7.     void Start()
  8.     {
  9.         int accumulator = 0;
  10.         string[] allInstructions = instructions.text.Split('\n');
  11.  
  12.         //Solve for Part 1
  13.         if(!Terminates(allInstructions, ref accumulator))
  14.         {
  15.             Debug.Log($"Program entered infinite loop with accumulator: {accumulator}");
  16.         }
  17.  
  18.         //Solve for Part 2
  19.         //Iterate through the program, swapping nop for jmp instructions and vice versa
  20.         //Check each version of the program for termination. If not, restore the original version and try the next instruction.
  21.         for(int i=0; i<allInstructions.Length-1; i++)
  22.         {
  23.             string original = allInstructions[i];
  24.  
  25.             //Change the instruction, swapping nop for jmp
  26.             (string op, int operand) = GetOpAndOperand(original);
  27.             if(op == "jmp")
  28.             {
  29.                 op = "nop";
  30.             }
  31.             else if(op == "nop")
  32.             {
  33.                 op = "jmp";
  34.             }
  35.             else
  36.             {
  37.                 continue; //Not an instruction we need to verify, go to next line.
  38.             }
  39.  
  40.             allInstructions[i] = $"{op} {operand}"; //Update the program with the new instruction.
  41.  
  42.             //Check if new instruction fixed the program.
  43.             if(Terminates(allInstructions, ref accumulator))
  44.             {
  45.                 Debug.Log($"Program terminated with change to line {i}, now reads: {allInstructions[i]}, accumulator: {accumulator}");
  46.                 break;
  47.             }
  48.  
  49.             //Restore the program to the original instruction for next attempt.
  50.             allInstructions[i] = original;
  51.         }
  52.     }
  53.  
  54.     // Determines if a program terminates or enters an infinite loop.
  55.     // program: the string representing the program, one instruction per line, in the format: operator operand
  56.     // accumulator: the value in the accumultor at the point just before the program begins an infinite loop or after termination.
  57.     // returns: true if it terminates, false otherwise.
  58.     bool Terminates(string[] program, ref int accumulator)
  59.     {
  60.         int acc = 0;
  61.         int programCounter = 0;
  62.  
  63.         HashSet<int> executed = new HashSet<int>();
  64.  
  65.         while (true)
  66.         {
  67.             //Leave the loop before executing an instruction twice.
  68.             if (executed.Contains(programCounter))
  69.             {
  70.                 accumulator = acc;
  71.                 return false;
  72.             }
  73.             executed.Add(programCounter);
  74.  
  75.             //Extract the operator and operand.
  76.             (string op, int operand) = (op, operand) = GetOpAndOperand(program[programCounter]);
  77.  
  78.             //Interpret and execute.
  79.             switch (op)
  80.             {
  81.                 case "nop":
  82.                     programCounter++;
  83.                     break;
  84.                 case "acc":
  85.                     acc += operand;
  86.                     programCounter++;
  87.                     break;
  88.                 case "jmp":
  89.                     programCounter += operand;
  90.                     break;
  91.                 default:
  92.                     Debug.LogError("Unexpected instruction encountered.");
  93.                     break;
  94.             }
  95.  
  96.             //Check to see if program counter points past the end of the program
  97.             if(programCounter == program.Length)
  98.             {
  99.                 accumulator = acc;
  100.                 return true;
  101.             }
  102.         }
  103.     }
  104.  
  105.     //Split an instruction into the operator and operand tuple
  106.     //EG: jmp -20 --> ("jmp", -20)
  107.     (string, int) GetOpAndOperand(string instruction)
  108.     {
  109.         string[] parts = instruction.Split(' ');
  110.         string op = parts[0];
  111.         int operand = int.Parse(parts[1]);
  112.         return (op, operand);
  113.     }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement