from typing import NamedTuple from utils import open_day class Win(NamedTuple): index: int | None round: int Board = list[list[int]] def board_from_string(s: str) -> Board: return [[numidxs[int(cell)] for cell in row.split()] for row in s.split('\n')] def resolve(nums: list[int], boards: list[Board], index: int, round: int) -> int: board: Board = boards[index] count: int = sum(nums[cell] for row in board for cell in row if cell > round) return count * nums[round] nums: str | list[int] boards: list[str] | list[Board] nums, *boards = open_day(4).read().rstrip().split('\n\n') nums = list(map(int, nums.split(','))) numidxs = { n: i for i, n in enumerate(nums) } boards = [board_from_string(board) for board in boards] first: Win = Win(None, max(nums)) last: Win = Win(None, 0) for i, board in enumerate(boards): win: Win = Win(i, min( min(max(row) for row in board), min(max(col) for col in zip(*board)) )) if win.round < first.round: first = win if win.round > last.round: last = win assert(first.index is not None and last.index is not None) print(resolve(nums, boards, first.index, first.round)) print(resolve(nums, boards, last.index, last.round))