summaryrefslogtreecommitdiffstats
path: root/day13/__init__.py
diff options
context:
space:
mode:
authorGravatar Tom van der Lee <tom@vanderlee.io>2021-12-13 19:18:02 +0100
committerGravatar Tom van der Lee <tom@vanderlee.io>2021-12-14 21:40:24 +0100
commit5b4e79cc749bd2d6451dc0b1fb03f5b500eb8873 (patch)
tree2d8b4c6a291e0ba641158394cccfa74f84b89e8b /day13/__init__.py
parent7bbeb8155521686bd9bbd28fec5cb91ffb8360af (diff)
download2021-5b4e79cc749bd2d6451dc0b1fb03f5b500eb8873.tar.gz
2021-5b4e79cc749bd2d6451dc0b1fb03f5b500eb8873.tar.bz2
2021-5b4e79cc749bd2d6451dc0b1fb03f5b500eb8873.zip
Day 13
Diffstat (limited to 'day13/__init__.py')
-rw-r--r--day13/__init__.py109
1 files changed, 109 insertions, 0 deletions
diff --git a/day13/__init__.py b/day13/__init__.py
new file mode 100644
index 0000000..41b81dc
--- /dev/null
+++ b/day13/__init__.py
@@ -0,0 +1,109 @@
1import re
2from abc import ABC
3from copy import copy
4from dataclasses import dataclass
5from typing import List, Tuple, Union, TypedDict
6
7from aoc import BaseAssignment
8
9Coordinate = Tuple[int, int]
10
11def mirrored_index(index: int, fold: int) -> int:
12 return fold + (fold - index)
13
14@dataclass
15class Sheet:
16 dots: List[Coordinate]
17 width: int = 0
18 height: int = 0
19
20 def __post_init__(self):
21 x_coordinates, y_coordinates = zip(*self.dots)
22
23 self.width = max(x_coordinates) + 1
24 self.height = max(y_coordinates) + 1
25
26
27 def fold_x(self, position: int):
28 for x, y in copy(self.dots):
29 mirrored_x = mirrored_index(x, position)
30 if mirrored_x < position:
31 self.dots.append((mirrored_x, y))
32 self.dots.remove((x, y))
33
34 self.width = self.width // 2
35 self.dots = list(set(self.dots))
36
37 def fold_y(self, position: int):
38 for x, y in copy(self.dots):
39 mirrored_y = mirrored_index(y, position)
40 if mirrored_y < position:
41 self.dots.append((x, mirrored_y))
42 self.dots.remove((x, y))
43
44 self.height = self.height // 2
45 self.dots = list(set(self.dots))
46
47 def __repr__(self):
48 dots = set(self.dots)
49 return '\n'.join([
50 '',
51 *[
52 ''.join([
53 '█' if (x, y) in dots else ' '
54 for x in range(self.width)
55 ])
56 for y in range(self.height)
57 ],
58 '',
59 ])
60
61class Instruction(TypedDict):
62 direction: str
63 position: int
64
65coordinate_regex = re.compile('(\d+),(\d+)')
66instruction_regex = re.compile('fold along (?P<direction>[xy])=(?P<position>\d+)')
67
68class Assignment(BaseAssignment, ABC):
69 def parse_item(self, item: str) -> Union[Coordinate,Instruction]:
70 if coordinate := coordinate_regex.match(item):
71 return tuple(int(i) for i in coordinate.groups())
72
73 if instruction := instruction_regex.match(item):
74 return {
75 **instruction.groupdict(),
76 'position': int(instruction.groupdict()['position'])
77 }
78
79 def read_input(self, example = False) -> Tuple[Sheet, List[Instruction]]:
80 input = super().read_input(example)
81
82 coordinates: List[Coordinate] = []
83
84 while True:
85 coordinate = next(input)
86 if coordinate is None:
87 break
88
89 coordinates.append(coordinate)
90
91 sheet = Sheet(dots=coordinates)
92
93 return sheet, list(input)
94
95
96class AssignmentOne(Assignment):
97 example_result = 17
98
99 def run(self, input: Tuple[Sheet, List[Instruction]]) -> int:
100 sheet, instructions = input
101 getattr(sheet, f'fold_{instructions[0]["direction"]}')(instructions[0]["position"])
102 return len(sheet.dots)
103
104class AssignmentTwo(Assignment):
105 def run(self, input: Tuple[Sheet, List[Instruction]]) -> Sheet:
106 sheet, instructions = input
107 for instruction in instructions:
108 getattr(sheet, f'fold_{instruction["direction"]}')(instruction["position"])
109 return sheet