use std::str::FromStr; use color_eyre::eyre::{eyre, Error}; use super::board::Board; #[derive(Debug)] pub struct Bingo { pub boards: Vec, pub numbers: Vec, } impl Bingo { /// The game loop for part one. /// /// Loops over the bingo numbers until it finds the first board that has won. pub fn play_until_first_win(mut self) -> (Board, i32) { for number in self.numbers { for board in &mut self.boards { board.mark_number(number); if board.check() { return (board.clone(), number); } } } unreachable!() } /// The game loop for part two. /// /// Loops over the bingo numbers until only one board is left and then returns /// that as the winner. pub fn play_until_last_win(mut self) -> (Board, i32) { for number in self.numbers { for board in &mut self.boards { board.mark_number(number); board.has_won = board.check(); } if self.boards.len() == 1 { return (self.boards.first().unwrap().clone(), number); } self.boards = self .boards .into_iter() .filter(|board| !board.has_won) .collect(); } unreachable!() } } impl FromStr for Bingo { type Err = Error; fn from_str(s: &str) -> Result { let numbers = s .split('\n') .next() .ok_or_else(|| eyre!("Didn't find bingo numbers on the first line"))? .split(',') .map(str::parse) .collect::>()?; let boards = s .split("\n\n") .skip(1) .map(str::parse) .collect::>()?; Ok(Self { boards, numbers }) } }