Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //Advent of Code 2020 Day 8 Parts 1 and 2 solution by Mike LeSauvage
- public class ProgramEvaluator : MonoBehaviour
- {
- [SerializeField] TextAsset instructions = null; //Hooked up in the input text in the Unity editor.
- // Start is a Unity method called once per program execution.
- void Start()
- {
- int accumulator = 0;
- string[] allInstructions = instructions.text.Split('\n');
- //Solve for Part 1
- if(!Terminates(allInstructions, ref accumulator))
- {
- Debug.Log($"Program entered infinite loop with accumulator: {accumulator}");
- }
- //Solve for Part 2
- //Iterate through the program, swapping nop for jmp instructions and vice versa
- //Check each version of the program for termination. If not, restore the original version and try the next instruction.
- for(int i=0; i<allInstructions.Length-1; i++)
- {
- string original = allInstructions[i];
- //Change the instruction, swapping nop for jmp
- (string op, int operand) = GetOpAndOperand(original);
- if(op == "jmp")
- {
- op = "nop";
- }
- else if(op == "nop")
- {
- op = "jmp";
- }
- else
- {
- continue; //Not an instruction we need to verify, go to next line.
- }
- allInstructions[i] = $"{op} {operand}"; //Update the program with the new instruction.
- //Check if new instruction fixed the program.
- if(Terminates(allInstructions, ref accumulator))
- {
- Debug.Log($"Program terminated with change to line {i}, now reads: {allInstructions[i]}, accumulator: {accumulator}");
- break;
- }
- //Restore the program to the original instruction for next attempt.
- allInstructions[i] = original;
- }
- }
- // Determines if a program terminates or enters an infinite loop.
- // program: the string representing the program, one instruction per line, in the format: operator operand
- // accumulator: the value in the accumultor at the point just before the program begins an infinite loop or after termination.
- // returns: true if it terminates, false otherwise.
- bool Terminates(string[] program, ref int accumulator)
- {
- int acc = 0;
- int programCounter = 0;
- HashSet<int> executed = new HashSet<int>();
- while (true)
- {
- //Leave the loop before executing an instruction twice.
- if (executed.Contains(programCounter))
- {
- accumulator = acc;
- return false;
- }
- executed.Add(programCounter);
- //Extract the operator and operand.
- (string op, int operand) = (op, operand) = GetOpAndOperand(program[programCounter]);
- //Interpret and execute.
- switch (op)
- {
- case "nop":
- programCounter++;
- break;
- case "acc":
- acc += operand;
- programCounter++;
- break;
- case "jmp":
- programCounter += operand;
- break;
- default:
- Debug.LogError("Unexpected instruction encountered.");
- break;
- }
- //Check to see if program counter points past the end of the program
- if(programCounter == program.Length)
- {
- accumulator = acc;
- return true;
- }
- }
- }
- //Split an instruction into the operator and operand tuple
- //EG: jmp -20 --> ("jmp", -20)
- (string, int) GetOpAndOperand(string instruction)
- {
- string[] parts = instruction.Split(' ');
- string op = parts[0];
- int operand = int.Parse(parts[1]);
- return (op, operand);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement