summaryrefslogtreecommitdiffstats
path: root/day10/__init__.py
blob: 62cc5be045b978384ad8ab67138c3d8bfeb2c812 (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
from dataclasses import dataclass
from functools import lru_cache, reduce
from typing import List, Generator, Dict, Optional

from aoc import BaseAssignment


class Assignment(BaseAssignment):
    def parse_item(self, item: str) -> int:
        return int(item)


class AssignmentOne(Assignment):
    def run(self, input: Generator) -> int:
        adapters = sorted(input)
        device_adapter = max(adapters) + 3

        adapter_list = [
            0, *adapters, device_adapter
        ]

        differences = [
            adapter_list[index + 1] - adapter
            for index, adapter in enumerate(adapter_list)
            if adapter != device_adapter
        ]

        return differences.count(1) * differences.count(3)


@dataclass
class Node:
    value: int
    next: List['Node']
    paths: int = 0

    def __repr__(self):
        return str(f'<Node: {self.value}, paths: {self.paths}>')

    def __post_init__(self):
        self.paths = reduce(lambda count, node: count + 1 if len(node.next) == 0 else count + node.paths, self.next, 0)


class AssignmentTwo(Assignment):
    def generate_graph(
            self, input: List, pointers: Dict[int, Node] = None) -> Optional[Node]:
        if pointers is None:
            pointers = {}

        if len(input) == 0:
            return

        value, next = input[0], input[1:]

        pointers[value] = Node(value=value, next=[
            (
                pointers[next_value]
                if next_value in pointers
                else self.generate_graph(
                    input=input[index + 1:],
                    pointers=pointers
                )
            )
            for index, next_value in enumerate(next[:3])
            if next_value - value <= 3
        ])

        return pointers[value]

    def run(self, input: Generator) -> int:
        adapters = sorted(input)
        device_adapter = max(adapters) + 3

        return self.generate_graph([0, *adapters, device_adapter]).paths