from tools.aoc import AOCDay from typing import Any class BingoCard: def __init__(self, numbers: str): numbers = list(map(int, numbers.split())) self.fields = {} self.checked = {} for y in range(5): for x in range(5): self.fields[(x, y)] = numbers[y * 5 + x] self.checked[(x, y)] = False def getScore(self, number: int) -> int: unmarked_score = 0 for x1 in range(5): for y1 in range(5): if not self.checked[(x1, y1)]: unmarked_score += self.fields[(x1, y1)] return unmarked_score * number def checkNumber(self, number: int) -> bool: if number not in self.fields.values(): return False for x in range(5): for y in range(5): if self.fields[(x, y)] == number: self.checked[(x, y)] = True for x in range(5): found_x = 0 found_y = 0 for y in range(5): if self.checked[(x, y)]: found_y += 1 if self.checked[(y, x)]: found_x += 1 if found_x == 5 or found_y == 5: return True return False class Day(AOCDay): inputs = [ [ (4512, "test_input04"), (58374, "input04") ], [ (1924, "test_input04"), (11377, "input04") ] ] def part1(self) -> Any: numbers_and_boards = self.getMultiLineInputAsArray(join_char=" ") numbers_drawn = list(map(int, numbers_and_boards[0].split(","))) cards = [BingoCard(cl) for cl in numbers_and_boards[1:]] for number in numbers_drawn: for i, card in enumerate(cards): if card.checkNumber(number): return card.getScore(number) def part2(self) -> Any: numbers_and_boards = self.getMultiLineInputAsArray(join_char=" ") numbers_drawn = list(map(int, numbers_and_boards[0].split(","))) cards = [BingoCard(cl) for cl in numbers_and_boards[1:]] for number in numbers_drawn: remaining_cards = cards.copy() for i, card in enumerate(cards): if card.checkNumber(number): if len(remaining_cards) == 1: return remaining_cards[0].getScore(number) remaining_cards.remove(card) cards = remaining_cards.copy() if __name__ == '__main__': day = Day(4) day.run(verbose=True)