From 5ba784ae1220ec930ffce9ea1ccbb1d6411f841e Mon Sep 17 00:00:00 2001 From: Tom van der Lee Date: Sat, 4 Dec 2021 12:31:52 +0100 Subject: Day 4 --- day4/__init__.py | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 day4/__init__.py (limited to 'day4/__init__.py') diff --git a/day4/__init__.py b/day4/__init__.py new file mode 100644 index 0000000..74c01f1 --- /dev/null +++ b/day4/__init__.py @@ -0,0 +1,121 @@ +from collections import Counter +from copy import copy +from dataclasses import dataclass +from typing import Iterator, List, Optional, Tuple, Callable + +from aoc import BaseAssignment + +def bold(item: str, condition: Callable[[], bool]): + return f'\033[36m{item}\033[0m' if condition() else item + +@dataclass +class Number: + nr: int + marked: bool = False + + def __int__(self): + return self.nr + + def __bool__(self): + return self.marked + + def __radd__(self, other): + return other + int(self) + + def mark(self): + self.marked = True + +@dataclass +class BingoCard: + card: List[List[Number]] + + @property + def bingo(self) -> bool: + return any([ + *[all(bool(item) for item in row) for row in self.card], + *[all(bool(row[col_index]) for row in self.card) for col_index in range(5)] + ]) + + def mark(self, nr: int): + for row in self.card: + for item in row: + if int(item) == nr: + item.mark() + + @property + def unmarked(self): + return [ + item + for row in self.card + for item in row + if not bool(item) + ] + + def __str__(self): + return '\n'.join([ + ''.join([ + bold(str(int(item)).rjust(2, ' ').ljust(3, ' '), lambda: item.marked) + for item in row + ]) + for row in self.card + ]) + + +class Assignment(BaseAssignment): + def read_input(self, example = False) -> Tuple[List[int], List[BingoCard]]: + cards = [] + card = None + + input = super().read_input(example) + nrs = [ int(n) for n in next(input).split(',') ] + + try: + row = next(input) + + while True: + if row == '': + if card is not None: + cards.append(BingoCard(card=card)) + card = [] + else: + card.append([ Number(nr=int(item)) for item in row.split(' ') if item != '']) + + row = next(input) + + except StopIteration: + if card is not None: + cards.append(BingoCard(card=card)) + + return nrs, cards + + +class AssignmentOne(Assignment): + example_result = 4512 + + def run(self, input: Tuple[List[int], List[BingoCard]]) -> int: + nrs, cards = input + + for nr in nrs: + for card in cards: + card.mark(nr) + + if card.bingo: + return nr * sum(card.unmarked) + + +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) \ No newline at end of file -- cgit v1.2.3