
Advent of Code: Day #08 - Handheld Halting
5 - 6 minutes
Introduction
Today we had to implement a very small instruction set with just three instructions, nop, acc, jmp.
Task One
For task one we're given a set of instructions that are stuck in an infinite loop and tasked to return the value in the accumulator before any instruction was ran for a second time.
Reading in the data
I read the data into an array of sub-arrays where each sub array was in the form ["instruction", number] where instruction is nop, acc or jmp and number is a positive or negative integer.
def read_data(path):dataset = []with open(path, "r") as file:for line in file.readlines():dataset.append(line.strip().split(" "))dataset[-1][1] = int(dataset[-1][1])return dataset
Computer Class
I have a feeling we may be asked to expand upon this instruction set in the coming days and weeks so I decided to make a class called Computer to run the instructions and contain all the logic.
class Computer:def __init__(self, instructions: list):self.running = Falseself.accumulator = 0self.current_operation = 0self.instructions = instructionsself.ran_instructions = []def reset(self, instructions: list):self.__init__(instructions)def run(self):self.running = Trueswitch = {"nop": self.nop,"acc": self.acc,"jmp": self.jmp}while self.running:instruction, number = self.instructions[self.current_operation]self.ran_instructions.append(self.current_operation)# Call the functionswitch[instruction](number)if self.current_operation in self.ran_instructions:return False, self.accumulatorif self.current_operation >= len(self.instructions):return True, self.accumulatordef nop(self, num: int):self.current_operation += 1returndef acc(self, num: int):self.accumulator += numself.current_operation += 1returndef jmp(self, num: int):num -= 1self.current_operation += numself.current_operation += 1return
The Solution
In the computer class I appended the current index to a list called ran_instructions. Every time the current_operation variable changes we check if it is in the ran_instructions list, if it is we stop running and return False to signal it was an incomplete execution and the current value of the accumulator.
def task_one(data):handheld = Computer(data)return handheld.run()[1]
Task Two
The Solution
For task two we are asked to fix the program. We are told that somewhere in the program a jmp and nop operation got swapped. Once we have fixed the program we are asked to return the value in the accumulator. My approach to this was brute force, go through all the nop and jmp instructions, swap them, and run the code to see if it works.
def task_two(data):new_data = deepcopy(data)handheld = Computer(data)last_index = 0# For all the index's of jmp or nop instructionsfor index in [index for index in range(len(data))if data[index][0] == "jmp"or data[index][0] == "nop"]:if last_index != 0: # Reset the last changenew_data[last_index][0] = "jmp"if new_data[last_index][0] == "nop"else "nop"# Change this instructionnew_data[index][0] = "jmp" if new_data[index][0] == "nop"else "nop"# Rest and re-runhandheld.reset(new_data)success = handheld.run()last_index = indexif success[0]:return success[1]
Links
Leaderboard Code: 353270-1fc6ef28
Github Repository A link to the github repo containing all the days.
main.py A direct download of the main.py script
2.5Kb