1
Fork 0
advent-of-code/source/year_2021/day_04/bingo.rs

78 lines
1.6 KiB
Rust

use std::str::FromStr;
use color_eyre::eyre::{eyre, Error};
use super::board::Board;
#[derive(Debug)]
pub struct Bingo {
pub boards: Vec<Board>,
pub numbers: Vec<i32>,
}
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<Self, Self::Err> {
let numbers = s
.split('\n')
.next()
.ok_or_else(|| eyre!("Didn't find bingo numbers on the first line"))?
.split(',')
.map(str::parse)
.collect::<Result<_, _>>()?;
let boards = s
.split("\n\n")
.skip(1)
.map(str::parse)
.collect::<Result<_, _>>()?;
Ok(Self { boards, numbers })
}
}