93 lines
2.5 KiB
Python
93 lines
2.5 KiB
Python
import collections
|
|
import re
|
|
|
|
# PART 1
|
|
|
|
|
|
class Instruction:
|
|
INSTRUCTION_RE = r"(\S+) (inc|dec) (-?\d+) if (\S+) (<|<=|>|>=|==|!=) (-?\d+)"
|
|
|
|
def __init__(self, register, mode, amount, c_register, c_operator, c_amount):
|
|
self.register = register
|
|
self.mode = mode
|
|
self.amount = amount
|
|
self.c_register = c_register
|
|
self.c_operator = c_operator
|
|
self.c_amount = c_amount
|
|
|
|
@classmethod
|
|
def from_line(cls, line):
|
|
match = re.fullmatch(cls.INSTRUCTION_RE, line)
|
|
|
|
register = match.group(1)
|
|
mode = match.group(2)
|
|
amount = int(match.group(3))
|
|
c_register = match.group(4)
|
|
c_operator = match.group(5)
|
|
c_amount = int(match.group(6))
|
|
|
|
return cls(register, mode, amount, c_register, c_operator, c_amount)
|
|
|
|
def compare_to(self, n):
|
|
if self.c_operator == "<":
|
|
return n < self.c_amount
|
|
elif self.c_operator == "<=":
|
|
return n <= self.c_amount
|
|
elif self.c_operator == ">":
|
|
return n > self.c_amount
|
|
elif self.c_operator == ">=":
|
|
return n >= self.c_amount
|
|
elif self.c_operator == "==":
|
|
return n == self.c_amount
|
|
elif self.c_operator == "!=":
|
|
return n != self.c_amount
|
|
|
|
def total(self):
|
|
if self.mode == "inc":
|
|
return self.amount
|
|
elif self.mode == "dec":
|
|
return -self.amount
|
|
|
|
|
|
class Machine:
|
|
def __init__(self, instructions):
|
|
self.instructions = instructions
|
|
self.reset()
|
|
|
|
def reset(self):
|
|
self.registers = collections.defaultdict(lambda: 0)
|
|
self.max_all_time = 0
|
|
|
|
@classmethod
|
|
def from_str(cls, s):
|
|
instructions = []
|
|
|
|
for line in s.splitlines():
|
|
instructions.append(Instruction.from_line(line))
|
|
|
|
return cls(instructions)
|
|
|
|
def execute_instruction(self, i):
|
|
c_amount = self.registers.get(i.c_register, 0)
|
|
if i.compare_to(c_amount):
|
|
self.registers[i.register] += i.total()
|
|
self.max_all_time = max(self.max_all_time, self.registers[i.register])
|
|
|
|
def execute(self):
|
|
for i in self.instructions:
|
|
self.execute_instruction(i)
|
|
|
|
def max_register(self):
|
|
return max(self.registers.values())
|
|
|
|
|
|
# PART 2
|
|
|
|
|
|
def solve(inputstr):
|
|
machine = Machine.from_str(inputstr)
|
|
machine.reset()
|
|
machine.execute()
|
|
max_register = machine.max_register()
|
|
print(f"Part 1: {max_register}")
|
|
print(f"Part 2: {machine.max_all_time}")
|