aoc-rs-2021/src/day_04/bingo.rs
2021-12-04 23:49:22 +01:00

90 lines
2.3 KiB
Rust

#[derive(Debug, Clone)]
pub struct Field {
pub number: usize,
pub marked: bool,
}
#[derive(Debug, Clone)]
pub struct Board {
pub fields: [[Field; 5]; 5],
pub finished: bool,
}
#[derive(Debug, Clone)]
pub struct Game {
pub boards: Vec<Board>,
pub input_numbers: Vec<usize>,
}
impl Board {
pub fn mark(&mut self, num: usize) -> Option<usize> {
if self.finished == true {
return None;
}
for lines in self.fields.iter_mut() {
for field in lines.iter_mut() {
if field.number == num {
field.marked = true;
}
}
}
if let Some(score) = self.bingo().map(|pre_score| pre_score * num) {
self.finished = true;
Some(score)
} else {
None
}
}
fn bingo(&self) -> Option<usize> {
let mut completed = false;
for i in 0..5 {
if (self.fields[i][0].marked
&& self.fields[i][1].marked
&& self.fields[i][2].marked
&& self.fields[i][3].marked
&& self.fields[i][4].marked)
|| (self.fields[0][i].marked
&& self.fields[1][i].marked
&& self.fields[2][i].marked
&& self.fields[3][i].marked
&& self.fields[4][i].marked)
{
completed = true;
}
}
if completed {
Some(self.pre_score())
} else {
None
}
}
fn pre_score(&self) -> usize {
self.fields
.iter()
.flat_map(|lines| lines.iter())
.map(|field| if field.marked { 0 } else { field.number })
.sum()
}
}
impl Game {
pub fn get_scores(mut self, max: Option<usize>) -> Vec<usize> {
let mut scores = Vec::new();
for num in self.input_numbers {
for board in &mut self.boards {
if let Some(score) = board.mark(num) {
scores.push(score);
if let Some(max) = max {
if scores.len() >= max {
return scores;
}
}
}
}
}
scores
}
}