Solution to problem 8 part 2 in Python
This commit is contained in:
88
src/P8.py
88
src/P8.py
@@ -1,3 +1,5 @@
|
|||||||
|
from typing import List, Tuple
|
||||||
|
|
||||||
# --- Day 8: Handheld Halting ---
|
# --- Day 8: Handheld Halting ---
|
||||||
|
|
||||||
# Your flight to the major airline hub reaches cruising altitude without
|
# 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?
|
# executed a second time, what value is in the accumulator?
|
||||||
|
|
||||||
with open("files/P8.txt", "r") as f:
|
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
|
acc = 0
|
||||||
executed = []
|
executed = []
|
||||||
nline = 0
|
nline = 0
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
instr = boot_code[nline]
|
instr = lines[nline]
|
||||||
if nline in executed:
|
if nline in executed:
|
||||||
# we are in a for loop :(
|
# we are in a for loop :(
|
||||||
break
|
break
|
||||||
@@ -94,10 +96,86 @@ def part_1() -> None:
|
|||||||
nline += 1
|
nline += 1
|
||||||
continue
|
continue
|
||||||
except IndexError:
|
except IndexError:
|
||||||
|
if debug:
|
||||||
print("Code has run successfully")
|
print("Code has run successfully")
|
||||||
|
return acc, True
|
||||||
|
if debug:
|
||||||
print(f"The value of the accumulator was {acc} before exiting")
|
print(f"The value of the accumulator was {acc} before exiting")
|
||||||
|
return acc, False
|
||||||
|
|
||||||
|
|
||||||
|
# --- 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__":
|
if __name__ == "__main__":
|
||||||
part_1()
|
part_1(lines, debug=True)
|
||||||
|
part_2()
|
||||||
|
|||||||
Reference in New Issue
Block a user