My solutions for Advent of Code.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
adventofcode/2020/8.py

130 lines
3.1 KiB

4 years ago
#!/usr/bin/env python
from aoc import get_input # AoC
import re # regex
from copy import copy
CodeLines = get_input(8).splitlines()
print(CodeLines)
def parseCode(code):
if( code and code != "" ):
regex = r"^([a-z]{3}) ([\+\-]{1})([0-9]+)$"
op, sign, num = re.match(regex, code).groups()
return op, sign, int(num)
else:
print("INVALID CODE:", code)
return
accu = 0
line = 0
def runCode(op, sign, num, newline=line, newaccu=accu):
if( op == "nop" ):
newline += 1
elif( op == "acc" ):
if( sign == "+" ):
newaccu += num
elif( sign == "-" ):
newaccu -= num
newline += 1
elif( op == "jmp" ):
if( sign == "+" ):
newline += num
elif( sign == "-" ):
newline -= num
return newline, newaccu
def swapCode(line, codes):
op, sign, num = parseCode(codes[line])
newcode = ""
if( op == "nop" ):
newcode = f"jmp {sign}{num}"
elif( op == "jmp" ):
newcode = f"nop {sign}{num}"
else:
return codes[line]
return newcode
def runProgram(codes=CodeLines, i=0, linefix=None, linecode=None, oldline=None):
print(f"\nRunning program iter:{i}")
print(f"Codes: {codes}")
seenLines = []
codeLen = len(codes)
line = 0
accu = 0
loop = False
while True:
try:
if( not loop ):
if( line < codeLen ):
code = codes[line]
op, sign, num = parseCode(code)
newline, newaccu = runCode(op, sign, num, line, accu)
print(f"op:{op} num:{sign}{num} line:{line}/{codeLen} newline:{newline}/{codeLen} accu:{accu} newaccu:{newaccu}")
if(newline in seenLines):
print(f"REPEAT AT: line:{line} newline:{newline} newaccu:{newaccu} seenLines:{seenLines}")
if( op == "jmp" ):
loop = True
print("LOOP")
seenLines.append(newline)
accu = newaccu
line = newline
else:
print("END OF PROGRAM")
print(accu, line)
return accu, line, codeLen
else:
print("BAD LOOP")
break
except:
print(f"ERROR line:{line} maxline:{codeLen}")
print(accu)
return accu, line, codeLen
count = 0
jmpThings = dict()
for l in range(len(CodeLines)):
code = CodeLines[l]
newcodes = CodeLines
op, sign, num = parseCode(code)
if( op == "nop" or op == "jmp" ):
jmpThings[l] = (op, sign, num)
print(jmpThings) # Need to change one of these
for codeline, ins in jmpThings.items():
print("\n\n####")
newcodes = copy(CodeLines)
newcodes[codeline] = swapCode(codeline, CodeLines)
print(f"newcodes:{newcodes} | {newcodes[codeline]}")
print(f"oldcodes:{CodeLines} | {CodeLines[codeline]}")
out = runProgram(newcodes)
print(f"OUT:{out}")
if( out ):
print("############ OUT:", out)
break
else:
continue