**commit** 8d22868e18fc047526d469f40ac82afa11ed24e7
**parent** e7ed6b6452079a11a247c10b0b337d42f1208ce9
**Author:** Eamon Caddigan <eamon.caddigan@gmail.com>
**Date:** Sat, 4 Dec 2021 21:28:33 -0500
Solution to day 4, part 2
**Diffstat:**

1 file changed, 40 insertions(+), 0 deletions(-)

**diff --git a/day04_part2.py b/day04_part2.py**
@@ -0,0 +1,40 @@
+#!/usr/bin/env python
+"""Very similar to part 1, except we run through all the numbers and find the
+last to win"""
+
+from utils import get_puzzle_input
+from day04_part1 import (parse_input,
+ mark_boards,
+ check_for_winner,
+ score_winning_board)
+
+def find_winning_board(board_df, number_draws):
+ """Given the df of board data and the list of numbers drawn, go through the
+ numbers and find the _last_ winning board. Returns a tuple containing the
+ sum of the unmarked elements on the final winning board and last drawn
+ number"""
+ # In this approach, we'll still work through the numbers sequentially.
+ # Every time we find a winner, we note its score and remove it from the
+ # list of boards, until we've run through all of the numbers.
+ last_winning_score = None
+ winning_number = None
+
+ for number_draw in number_draws:
+ board_df = mark_boards(board_df, number_draw)
+ while (winning_board := check_for_winner(board_df)) is not None:
+ last_winning_score = score_winning_board(board_df, winning_board)
+ winning_number = number_draw
+
+ # Remove this board so we stop looking at it
+ board_df = board_df.loc[board_df['board'] != winning_board]
+
+ return last_winning_score * winning_number
+
+def solve_puzzle(input_string):
+ """Return the numeric solution to the puzzle"""
+ # 684 ms ± 7.04 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
+ return find_winning_board(*parse_input(input_string))
+
+if __name__ == "__main__":
+ print("Last winning puzzle score:",
+ solve_puzzle(get_puzzle_input(4)))