Solution to problem 8 part 2 in Python

This commit is contained in:
David Doblas Jiménez 2021-11-25 22:10:16 +01:00
parent d44bade1e4
commit 49d870233a

View File

@ -1,3 +1,5 @@
from typing import List, Tuple
# --- Day 8: Handheld Halting ---
# Your flight to the major airline hub reaches cruising altitude without
@ -68,16 +70,16 @@
# executed a second time, what value is in the accumulator?
with open("files/P8.txt", "r") as f:
boot_code = [code for code in f.read().strip().split("\n")]
lines = [code for code in f.read().strip().split("\n")]
def part_1() -> None:
def part_1(lines: List[str], debug: bool = False) -> Tuple[int, bool]:
acc = 0
executed = []
nline = 0
while True:
try:
instr = boot_code[nline]
instr = lines[nline]
if nline in executed:
# we are in a for loop :(
break
@ -94,10 +96,86 @@ def part_1() -> None:
nline += 1
continue
except IndexError:
print("Code has run successfully")
if debug:
print("Code has run successfully")
return acc, True
if debug:
print(f"The value of the accumulator was {acc} before exiting")
return acc, False
print(f"The value of the accumulator was {acc} before exiting")
# --- Part Two ---
# After some careful analysis, you believe that exactly one instruction is
# corrupted.
# Somewhere in the program, either a jmp is supposed to be a nop, or a nop is
# supposed to be a jmp. (No acc instructions were harmed in the corruption of
# this boot code.)
# The program is supposed to terminate by attempting to execute an instruction
# immediately after the last instruction in the file. By changing exactly one
# jmp or nop, you can repair the boot code and make it terminate correctly.
# For example, consider the same program from above:
# nop +0
# acc +1
# jmp +4
# acc +3
# jmp -3
# acc -99
# acc +1
# jmp -4
# acc +6
# If you change the first instruction from nop +0 to jmp +0, it would create a
# single-instruction infinite loop, never leaving that instruction. If you
# change almost any of the jmp instructions, the program will still eventually
# find another jmp instruction and loop forever.
# However, if you change the second-to-last instruction (from jmp -4 to
# nop -4), the program terminates! The instructions are visited in this order:
# nop +0 | 1
# acc +1 | 2
# jmp +4 | 3
# acc +3 |
# jmp -3 |
# acc -99 |
# acc +1 | 4
# nop -4 | 5
# acc +6 | 6
# After the last instruction (acc +6), the program terminates by attempting to
# run the instruction below the last instruction in the file. With this change,
# after the program terminates, the accumulator contains the value 8 (acc +1,
# acc +1, acc +6).
# Fix the program so that it terminates normally by changing exactly one jmp
# (to nop) or nop (to jmp). What is the value of the accumulator after the
# program terminates?
def part_2() -> None:
for nline, _ in enumerate(lines):
inst = lines[nline]
# change instructions
if inst[:3] == "nop":
new_inst = "jmp"
elif inst[:3] == "jmp":
new_inst = "nop"
# make a copy of the original code
new_lines = lines.copy()
# change line according to the instructions in the original code
new_lines[nline] = " ".join((new_inst, inst[4:]))
acc, has_ended = part_1(new_lines)
if has_ended:
print(f"The value of the accumulator was {acc} after terminates")
break
if __name__ == "__main__":
part_1()
part_1(lines, debug=True)
part_2()