From 5b4e79cc749bd2d6451dc0b1fb03f5b500eb8873 Mon Sep 17 00:00:00 2001 From: Tom van der Lee Date: Mon, 13 Dec 2021 19:18:02 +0100 Subject: Day 13 --- day13/__init__.py | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 day13/__init__.py (limited to 'day13/__init__.py') 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 @@ +import re +from abc import ABC +from copy import copy +from dataclasses import dataclass +from typing import List, Tuple, Union, TypedDict + +from aoc import BaseAssignment + +Coordinate = Tuple[int, int] + +def mirrored_index(index: int, fold: int) -> int: + return fold + (fold - index) + +@dataclass +class Sheet: + dots: List[Coordinate] + width: int = 0 + height: int = 0 + + def __post_init__(self): + x_coordinates, y_coordinates = zip(*self.dots) + + self.width = max(x_coordinates) + 1 + self.height = max(y_coordinates) + 1 + + + def fold_x(self, position: int): + for x, y in copy(self.dots): + mirrored_x = mirrored_index(x, position) + if mirrored_x < position: + self.dots.append((mirrored_x, y)) + self.dots.remove((x, y)) + + self.width = self.width // 2 + self.dots = list(set(self.dots)) + + def fold_y(self, position: int): + for x, y in copy(self.dots): + mirrored_y = mirrored_index(y, position) + if mirrored_y < position: + self.dots.append((x, mirrored_y)) + self.dots.remove((x, y)) + + self.height = self.height // 2 + self.dots = list(set(self.dots)) + + def __repr__(self): + dots = set(self.dots) + return '\n'.join([ + '', + *[ + ''.join([ + '█' if (x, y) in dots else ' ' + for x in range(self.width) + ]) + for y in range(self.height) + ], + '', + ]) + +class Instruction(TypedDict): + direction: str + position: int + +coordinate_regex = re.compile('(\d+),(\d+)') +instruction_regex = re.compile('fold along (?P[xy])=(?P\d+)') + +class Assignment(BaseAssignment, ABC): + def parse_item(self, item: str) -> Union[Coordinate,Instruction]: + if coordinate := coordinate_regex.match(item): + return tuple(int(i) for i in coordinate.groups()) + + if instruction := instruction_regex.match(item): + return { + **instruction.groupdict(), + 'position': int(instruction.groupdict()['position']) + } + + def read_input(self, example = False) -> Tuple[Sheet, List[Instruction]]: + input = super().read_input(example) + + coordinates: List[Coordinate] = [] + + while True: + coordinate = next(input) + if coordinate is None: + break + + coordinates.append(coordinate) + + sheet = Sheet(dots=coordinates) + + return sheet, list(input) + + +class AssignmentOne(Assignment): + example_result = 17 + + def run(self, input: Tuple[Sheet, List[Instruction]]) -> int: + sheet, instructions = input + getattr(sheet, f'fold_{instructions[0]["direction"]}')(instructions[0]["position"]) + return len(sheet.dots) + +class AssignmentTwo(Assignment): + def run(self, input: Tuple[Sheet, List[Instruction]]) -> Sheet: + sheet, instructions = input + for instruction in instructions: + getattr(sheet, f'fold_{instruction["direction"]}')(instruction["position"]) + return sheet -- cgit v1.2.3