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

79 lines
1.7 KiB
Rust
Raw Normal View History

2024-01-14 21:04:10 +00:00
//! [`Bingo`] code and implementation.
2021-12-04 13:15:12 +00:00
use std::str::FromStr;
use color_eyre::eyre::{eyre, Error};
use super::board::Board;
2024-01-14 21:04:10 +00:00
/// The game of bingo to play with its boards and numbers.
2021-12-04 13:15:12 +00:00
#[derive(Debug)]
pub struct Bingo {
2024-01-14 21:04:10 +00:00
/// The list of [`Board`]s to play bingo with.
2021-12-04 13:15:12 +00:00
pub boards: Vec<Board>,
2024-01-14 21:04:10 +00:00
/// The list of numbers to play.
2021-12-04 13:15:12 +00:00
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);
}
2022-10-03 11:02:39 +00:00
self.boards.retain(|board| !board.has_won);
2021-12-04 13:15:12 +00:00
}
unreachable!()
}
}
impl FromStr for Bingo {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let numbers = s
.split('\n')
2021-12-04 13:15:12 +00:00
.next()
.ok_or_else(|| eyre!("Didn't find bingo numbers on the first line"))?
.split(',')
2021-12-04 13:15:12 +00:00
.map(str::parse)
.collect::<Result<_, _>>()?;
let boards = s
.split("\n\n")
.skip(1)
.map(str::parse)
.collect::<Result<_, _>>()?;
Ok(Self { boards, numbers })
}
}