2020-12-08 - Handheld Halting
(original .ipynb)
Day 8 is a simple assembly-code like program (mine is here) which can execute one of three operations (nop, acc and jmp). Part 1 involves interpreting the program and finding the value of the accumulator register at the point that it begins to enter an infinite loop. Part 2 involves "fixing" one of the instructions - swapping a nop to a jmp or vice versa - such that the program doesn't hit an infinite loop, but instead runs to the end of the program.
test_input_str = """nop +0
acc +1
jmp +4
acc +3
jmp -3
acc -99
acc +1
jmp -4
acc +6"""
puzzle_input_str = open("puzzle_input/day8.txt", "r").read()
def step(instructions, pc, acc):
opcode, arg = instructions[pc].split(" ")
new_pc = pc + 1
if opcode == "acc":
acc += int(arg)
elif opcode == "jmp":
new_pc = pc + int(arg)
elif opcode == "nop":
pass
return (new_pc, acc)
def try_run(raw_instructions):
instructions = raw_instructions.split("\n")
pc = 0
acc = 0
terminal_pc = len(instructions)
pc_visited = set()
while not (pc in pc_visited):
if pc == terminal_pc:
return (True, acc)
pc_visited.add(pc)
pc, acc = step(instructions, pc, acc)
return (False, acc)
assert (False, 5) == try_run(test_input_str)
try_run(puzzle_input_str)
(False, 1723)
def mutate_program(addr, raw_instructions):
instructions = raw_instructions.split("\n")
opcode, arg = instructions[addr].split(" ")
if opcode == "jmp":
opcode = "nop"
elif opcode == "nop":
opcode = "jmp"
else:
pass
instructions[addr] = f"{opcode} {arg}"
return "\n".join(instructions) #lol
def find_dodgy_instr(raw_instructions):
len_instructions = len(raw_instructions.split("\n"))
for n in range(len_instructions):
new_raw_instructions = mutate_program(n, raw_instructions)
success, final_acc = try_run(new_raw_instructions)
if success:
return final_acc
assert 8 == find_dodgy_instr(test_input_str)
find_dodgy_instr(puzzle_input_str)
846