95 lines
2.2 KiB
Python
95 lines
2.2 KiB
Python
|
#! /usr/bin/env python3
|
||
|
from copy import copy
|
||
|
|
||
|
sample = [
|
||
|
"nop +0",
|
||
|
"acc +1",
|
||
|
"jmp +4",
|
||
|
"acc +3",
|
||
|
"jmp -3",
|
||
|
"acc -99",
|
||
|
"acc +1",
|
||
|
"jmp -4",
|
||
|
"acc +6",
|
||
|
]
|
||
|
|
||
|
|
||
|
def parse_lines(lines):
|
||
|
def parse_line(line):
|
||
|
inst, _, num = line.partition(" ")
|
||
|
return (inst, int(num))
|
||
|
|
||
|
return [
|
||
|
parse_line(line)
|
||
|
for line in lines
|
||
|
]
|
||
|
|
||
|
|
||
|
def run_line(instructions, index):
|
||
|
inst, num = instructions[index]
|
||
|
if inst == "nop":
|
||
|
return index+1, 0
|
||
|
elif inst == "acc":
|
||
|
return index+1, num
|
||
|
elif inst == "jmp":
|
||
|
return index+num, 0
|
||
|
|
||
|
|
||
|
def part1():
|
||
|
with open("input.txt") as f:
|
||
|
instructions = parse_lines(f)
|
||
|
_, acc = run_until_loop(instructions, 0)
|
||
|
print("Total accumulated:", acc)
|
||
|
|
||
|
|
||
|
def run_until_loop(instructions, line, seen_lines=None):
|
||
|
if seen_lines is None:
|
||
|
seen_lines = set()
|
||
|
acc = 0
|
||
|
while line < len(instructions):
|
||
|
seen_lines.add(line)
|
||
|
# print(f"Inner: {line}:{instructions[line]}")
|
||
|
line, num = run_line(instructions, line)
|
||
|
acc += num
|
||
|
if line in seen_lines:
|
||
|
# print(f"Inner loop, break out")
|
||
|
return True, acc
|
||
|
return False, acc
|
||
|
|
||
|
|
||
|
def part2():
|
||
|
with open("input.txt") as f:
|
||
|
instructions = parse_lines(f)
|
||
|
|
||
|
accum = 0
|
||
|
line = 0
|
||
|
seen_lines = set()
|
||
|
|
||
|
while line < len(instructions):
|
||
|
if line in seen_lines:
|
||
|
print(f"Ugh, looping")
|
||
|
return
|
||
|
|
||
|
# print(f"{line}:{instructions[line]}")
|
||
|
inst, num = instructions[line]
|
||
|
if inst != "acc":
|
||
|
# print(f"Found an alternate, check for loop")
|
||
|
# Possible change
|
||
|
new_inst = copy(instructions)
|
||
|
new_seen = copy(seen_lines)
|
||
|
new_inst[line] = ("nop" if inst == "jmp" else "jmp", num)
|
||
|
has_loop, acc_d = run_until_loop(new_inst, line, new_seen)
|
||
|
if not has_loop:
|
||
|
accum += acc_d
|
||
|
print(f"Found solution! Changing {line}: Total {accum}")
|
||
|
return
|
||
|
|
||
|
seen_lines.add(line)
|
||
|
line, num = run_line(instructions, line)
|
||
|
accum += num
|
||
|
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
part1()
|
||
|
part2()
|