summaryrefslogtreecommitdiffstats
path: root/day10/__init__.py
blob: e6d385afe637d1f2d243e10c9940ea52a855488c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# -*- 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)]
        )