advent-of-code/2022/10/python/main.py

108 lines
2.7 KiB
Python
Raw Normal View History

2022-12-10 13:35:52 +01:00
#!/usr/bin/env python
from os.path import dirname, join
from typing import Literal, Union
# Day 10
# Common
def read_input(filename):
data = join(dirname(__file__), '..', filename)
with open(data) as f:
return f.read().strip()
test = read_input('test.txt')
data = read_input('input.txt')
Instruction = tuple[int, Union[
tuple[Literal['noop']],
tuple[Literal['addx'], int]
]]
class CRT:
def __init__(self) -> None:
self.clock = 0
self.display = [
['.' for _ in range(40)]
for _ in range(6)
]
def step(self, position: int):
sprite = self.clock % 40
if position - 1 <= sprite and sprite <= position+1:
y = self.clock // 40
x = sprite
self.display[y][x] = "#"
self.clock += 1
def __str__(self) -> str:
return '\n'.join(map(lambda line: ''.join(line), self.display))
class CPU:
def __init__(self, instructions: list[Instruction]) -> None:
self.instructions = instructions
self.cycle = 1
self.register = 1
self.processing: Instruction = self.instructions.pop(0)
self.crt = CRT()
def step(self) -> bool:
self.cycle += 1
count, instruction = self.processing
if count > 1:
self.processing = (count-1, instruction)
else:
match instruction[0]:
case 'noop':
pass
case 'addx':
self.register += instruction[1]
if len(self.instructions) == 0:
return True
self.processing = self.instructions.pop(0)
return False
def signal_strength(self):
return self.cycle * self.register
def run(self):
signals = 0
while True:
self.crt.step(self.register)
halted = self.step()
if (self.cycle + 20) % 40 == 0:
signals += self.signal_strength()
if halted:
break
return signals
def __str__(self) -> str:
return f"{self.cycle} X={self.register} {self.processing} SS={self.signal_strength()}\n{self.crt}"
@staticmethod
def parse(data: str):
instructions: list[Instruction] = []
for line in data.splitlines():
command, *args = line.split()
match command:
case 'noop':
instructions.append((1, (command, )))
case 'addx':
instructions.append((2, (command, int(args[0]))))
return CPU(instructions)
# Running
cpu = CPU.parse(test)
print(cpu.run())
print(cpu)
cpu = CPU.parse(data)
print(cpu.run())
print(cpu)