from collections import Counter from copy import copy from dataclasses import dataclass from typing import Iterator, List, Optional, Tuple, Callable from aoc import BaseAssignment Vector = Tuple[Tuple[int, int], Tuple[int, int]] class Assignment(BaseAssignment): def parse_item(self, item: str) -> Vector: start, end = item.split('->') return ( tuple(int(_) for _ in start.strip().split(',')), tuple(int(_) for _ in end.strip().split(',')), ) def read_input(self, example = False) -> List[Vector]: return list(super().read_input(example)) def is_horizontal(v: Vector): return v[0][0] == v[1][0] def is_vertical(v: Vector): return v[0][1] == v[1][1] def points_in_vector(vector: Vector) -> List[Tuple[int, int]]: first_x = min(vector[0][0], vector[1][0]) last_x = max(vector[0][0], vector[1][0]) first_y = min(vector[0][1], vector[1][1]) last_y = max(vector[0][1], vector[1][1]) return [ (vector[0][0], y) for y in range(first_y, last_y + 1) ] if is_horizontal(vector) else [ (x, vector[0][1]) for x in range(first_x, last_x + 1) ] if is_vertical(vector) else [] class AssignmentOne(Assignment): example_result = 5 def run(self, input: List[Vector]) -> int: coordinates = [] for vector in input: coordinates += points_in_vector(vector) return len([c for c in Counter(coordinates).values() if c >= 2]) # class AssignmentTwo(Assignment): # example_result = 1924 # # def run(self, input: Tuple[List[int], List[BingoCard]]) -> int: # nrs, cards = input # # in_game = copy(cards) # for nr in nrs: # for card in copy(in_game): # card.mark(nr) # # if card.bingo: # in_game.remove(card) # # if len(in_game) == 0: # return nr * sum(card.unmarked)