Skip to content

Instantly share code, notes, and snippets.

@and-reas-se
Created December 4, 2021 22:27
Show Gist options
  • Save and-reas-se/0a4c77f150715213e753b5f9ce8a7238 to your computer and use it in GitHub Desktop.
Save and-reas-se/0a4c77f150715213e753b5f9ce8a7238 to your computer and use it in GitHub Desktop.
Advent of Code day 4 in rust
fn main() {
let input_file = std::env::args().nth(1).expect("Input filename missing");
let input = std::fs::read_to_string(input_file).expect("Error reading file");
let numbers = input
.lines()
.next()
.unwrap()
.split(',')
.map(|num| num.parse().expect("invalid number"))
.collect();
let mut cards = Vec::new();
let mut buffer = String::new();
let mut count = 0;
for line in input.lines().skip(1) {
count += 1;
buffer.push_str(line);
buffer.push(' ');
if count == 6 {
cards.push(BingoCard::new_from_str(&buffer));
buffer.clear();
count = 0;
}
}
let answer = question1(&numbers, &mut cards.clone());
println!("Answer to question 1: {}", answer);
let answer = question2(&numbers, &mut cards);
println!("Answer to question 1: {}", answer);
}
fn question1(numbers: &Vec<u32>, cards: &mut Vec<BingoCard>) -> u32 {
for number in numbers {
for card in cards.iter_mut() {
if let Some(score) = card.mark(*number) {
return score;
}
}
}
0
}
fn question2(numbers: &Vec<u32>, cards: &mut Vec<BingoCard>) -> u32 {
let mut last_score = 0;
for number in numbers {
for card in cards.iter_mut().filter(|item| !item.is_won()) {
if let Some(score) = card.mark(*number) {
last_score = score;
}
}
}
last_score
}
#[derive(Debug, Clone)]
struct BingoCard {
squares: Vec<u32>,
marks: [bool; 25],
row_marks: [u32; 5],
col_marks: [u32; 5],
is_won: bool,
}
impl BingoCard {
/// NOTE: This will panic if the bingo square is not 5x5
fn new_from_str(text: &str) -> Self {
let squares: Vec<u32> = text
.split_whitespace()
.map(|num| num.parse().expect("error parsing bingo square"))
.collect();
assert_eq!(squares.len(), 25, "invalid bingo board size: {:#?}", text);
Self {
squares,
marks: [false; 25],
row_marks: [0; 5],
col_marks: [0; 5],
is_won: false,
}
}
fn is_won(&self) -> bool {
self.is_won
}
/// returns Some(score) if we won, otherwise returns None
/// assumes numbers in bingo squares are unique
fn mark(&mut self, number: u32) -> Option<u32> {
if let Some((idx, _)) = self
.squares
.iter()
.enumerate()
.find(|(_, value)| **value == number)
{
let col_idx = idx % 5;
let row_idx = idx / 5;
self.marks[idx] = true;
self.row_marks[row_idx] += 1;
self.col_marks[col_idx] += 1;
if self.row_marks[row_idx] == 5 || self.col_marks[col_idx] == 5 {
self.is_won = true;
return Some(self.sum_of_unmarked_squares() * number);
}
}
None
}
fn sum_of_unmarked_squares(&self) -> u32 {
self.squares
.iter()
.enumerate()
.filter(|(idx, _)| !self.marks[*idx])
.map(|(_, value)| value)
.sum()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment