# -*- coding: utf-8 -*- from abc import ABC from functools import lru_cache from typing import Iterator, List, Dict, Any from aoc import BaseAssignment class Assignment(BaseAssignment, ABC): def __init__(self, path): super().__init__(path) self.x_history = {1: 1} def addx(self, value: str) -> Iterator[int]: yield 0 yield int(value) def noop(self) -> Iterator: yield 0 def x_after(self, cycles: int, instructions: List[str]): try: return self.x_history[cycles] except KeyError: pass cycle = 1 x = 1 while cycle <= cycles and len(instructions) > 0: instruction, *instructions = instructions instruction, *args = instruction.split(" ") for val in getattr(self, instruction)(*args): x += val cycle += 1 self.x_history[cycle] = x return self.x_history[cycles] class AssignmentOne(Assignment): example_result = 13140 def run(self, input: Iterator) -> int: instructions = list(input) return sum( [ cycles * self.x_after(cycles, instructions) for cycles in [220, 180, 140, 100, 60, 20] ] ) class AssignmentTwo(Assignment): example_result = """##..##..##..##..##..##..##..##..##..##.. ###...###...###...###...###...###...###. ####....####....####....####....####.... #####.....#####.....#####.....#####..... ######......######......######......#### #######.......#######.......#######.....""" def render_pixel(self, row: int, col: int, instructions: List[str]): cycle = row * 40 + col x_register = self.x_after(cycle, instructions) if col in [x_register - 1, x_register, x_register + 1]: return "#" return "." def run(self, input: Iterator) -> str: instructions = list(input) screen = [ [ self.render_pixel(row, col, instructions) for col in reversed(range(1, 41)) ] for row in reversed(range(6)) ] return "\n".join( ["".join(reversed([str(i) for i in row])) for row in reversed(screen)] )