day04_part2.py (1679B)
1 #!/usr/bin/env python 2 """Very similar to part 1, except we run through all the numbers and find the 3 last to win""" 4 5 from utils import get_puzzle_input 6 from day04_part1 import (parse_input, 7 mark_boards, 8 check_for_winner, 9 score_winning_board) 10 11 def find_winning_board(board_df, number_draws): 12 """Given the df of board data and the list of numbers drawn, go through the 13 numbers and find the _last_ winning board. Returns a tuple containing the 14 sum of the unmarked elements on the final winning board and last drawn 15 number""" 16 # In this approach, we'll still work through the numbers sequentially. 17 # Every time we find a winner, we note its score and remove it from the 18 # list of boards, until we've run through all of the numbers. 19 last_winning_score = None 20 winning_number = None 21 22 for number_draw in number_draws: 23 board_df = mark_boards(board_df, number_draw) 24 while (winning_board := check_for_winner(board_df)) is not None: 25 last_winning_score = score_winning_board(board_df, winning_board) 26 winning_number = number_draw 27 28 # Remove this board so we stop looking at it 29 board_df = board_df.loc[board_df['board'] != winning_board] 30 31 return last_winning_score * winning_number 32 33 def solve_puzzle(input_string): 34 """Return the numeric solution to the puzzle""" 35 # 684 ms ± 7.04 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) 36 return find_winning_board(*parse_input(input_string)) 37 38 if __name__ == "__main__": 39 print("Last winning puzzle score:", 40 solve_puzzle(get_puzzle_input(4)))