#!/usr/bin/env python # 2021 - Advent Of Code - 4 part 2 import re re_parse = re.compile(r'\s?(\d+)\s+'*4 + r'(\d+)') GRID_SIZE = 5 class Board: def __init__(self, grid): self.grid = grid self.marked = [[0] * GRID_SIZE for _ in range(GRID_SIZE)] def print_with_mark(self): for x in range(GRID_SIZE): print(f'{self.grid[x]} \t {self.marked[x]}') def mark_number(self, num): for line in range(GRID_SIZE): try: index = self.grid[line].index(num) self.marked[line][index] = 1 if self.has_win(): return True return False except ValueError: pass return False def has_win(self): # check lines for line in range(GRID_SIZE): if 0 not in self.marked[line]: return True # check column for c in range(GRID_SIZE): col_sum = 0 for line in range(GRID_SIZE): if self.marked[line][c] == 0: break col_sum += 1 if col_sum == GRID_SIZE: return True return False def calc_unmarked(self): unmarked_sum = 0 for line in range(GRID_SIZE): for col in range(GRID_SIZE): if self.marked[line][col] == 0: unmarked_sum += int(self.grid[line][col]) return unmarked_sum def parse_file(file): boards_list = [] with open(file, encoding="utf-8") as f: numbers = f.readline().split(',') line = f.readline() while line: board = [] for _ in range(GRID_SIZE): line = f.readline() m = re_parse.match(line) grid_line = m.groups() board.append(grid_line) b = Board(board) boards_list.append(b) line = f.readline() return boards_list, numbers def play(boards_list, draws): """ call all numbers could stop when all boards have won ;-) """ winners = [] for d in draws: print(f'calling {d}') winner = () round_winners = [] for board in boards_list: if board.mark_number(d): print("this board wins !") board.print_with_mark() winner = (board, d) round_winners.append(winner) if winner: print(f'round winners: {len(round_winners)}') for r in round_winners: boards_list.remove(r[0]) winners.extend(round_winners) print(f'number of winners: {len(winners)}') return winners boards, calls = parse_file('input.txt') print(f'number of boards: {len(boards)}') # (winning_board, last_num) = play_until_win(boards, draws) winning_boards = play(boards, calls) winning_board, last_num = winning_boards[-1] print(f'last number is: {last_num}') board_score = winning_board.calc_unmarked() print(f'board score: {board_score}') score = int(last_num) * board_score print(f'score is : {score}')