diff options
| author | 2020-12-18 00:49:00 +0100 | |
|---|---|---|
| committer | 2020-12-18 00:49:00 +0100 | |
| commit | 6c18350a39ddb701fe34676a84b91dec0848160a (patch) | |
| tree | f3d7da4dd2b979d1a9855a48a883ed2d052dc249 /day10/__init__.py | |
| parent | 37aa8eec0498d7e8491084711132f16db9129a39 (diff) | |
| download | 2020-master.tar.gz 2020-master.tar.bz2 2020-master.zip | |
Diffstat (limited to 'day10/__init__.py')
| -rw-r--r-- | day10/__init__.py | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/day10/__init__.py b/day10/__init__.py new file mode 100644 index 0000000..62cc5be --- /dev/null +++ b/day10/__init__.py | |||
| @@ -0,0 +1,74 @@ | |||
| 1 | from dataclasses import dataclass | ||
| 2 | from functools import lru_cache, reduce | ||
| 3 | from typing import List, Generator, Dict, Optional | ||
| 4 | |||
| 5 | from aoc import BaseAssignment | ||
| 6 | |||
| 7 | |||
| 8 | class Assignment(BaseAssignment): | ||
| 9 | def parse_item(self, item: str) -> int: | ||
| 10 | return int(item) | ||
| 11 | |||
| 12 | |||
| 13 | class AssignmentOne(Assignment): | ||
| 14 | def run(self, input: Generator) -> int: | ||
| 15 | adapters = sorted(input) | ||
| 16 | device_adapter = max(adapters) + 3 | ||
| 17 | |||
| 18 | adapter_list = [ | ||
| 19 | 0, *adapters, device_adapter | ||
| 20 | ] | ||
| 21 | |||
| 22 | differences = [ | ||
| 23 | adapter_list[index + 1] - adapter | ||
| 24 | for index, adapter in enumerate(adapter_list) | ||
| 25 | if adapter != device_adapter | ||
| 26 | ] | ||
| 27 | |||
| 28 | return differences.count(1) * differences.count(3) | ||
| 29 | |||
| 30 | |||
| 31 | @dataclass | ||
| 32 | class Node: | ||
| 33 | value: int | ||
| 34 | next: List['Node'] | ||
| 35 | paths: int = 0 | ||
| 36 | |||
| 37 | def __repr__(self): | ||
| 38 | return str(f'<Node: {self.value}, paths: {self.paths}>') | ||
| 39 | |||
| 40 | def __post_init__(self): | ||
| 41 | self.paths = reduce(lambda count, node: count + 1 if len(node.next) == 0 else count + node.paths, self.next, 0) | ||
| 42 | |||
| 43 | |||
| 44 | class AssignmentTwo(Assignment): | ||
| 45 | def generate_graph( | ||
| 46 | self, input: List, pointers: Dict[int, Node] = None) -> Optional[Node]: | ||
| 47 | if pointers is None: | ||
| 48 | pointers = {} | ||
| 49 | |||
| 50 | if len(input) == 0: | ||
| 51 | return | ||
| 52 | |||
| 53 | value, next = input[0], input[1:] | ||
| 54 | |||
| 55 | pointers[value] = Node(value=value, next=[ | ||
| 56 | ( | ||
| 57 | pointers[next_value] | ||
| 58 | if next_value in pointers | ||
| 59 | else self.generate_graph( | ||
| 60 | input=input[index + 1:], | ||
| 61 | pointers=pointers | ||
| 62 | ) | ||
| 63 | ) | ||
| 64 | for index, next_value in enumerate(next[:3]) | ||
| 65 | if next_value - value <= 3 | ||
| 66 | ]) | ||
| 67 | |||
| 68 | return pointers[value] | ||
| 69 | |||
| 70 | def run(self, input: Generator) -> int: | ||
| 71 | adapters = sorted(input) | ||
| 72 | device_adapter = max(adapters) + 3 | ||
| 73 | |||
| 74 | return self.generate_graph([0, *adapters, device_adapter]).paths | ||
