Implementation day 4 2021

This commit is contained in:
2021-12-04 10:43:02 +01:00
parent 612d3ecb6b
commit fb358be8f0
3 changed files with 750 additions and 4 deletions

View File

@@ -1,9 +1,135 @@
use std::collections::HashMap;
use std::io::Read;
pub fn part1(_input: &mut dyn Read) -> String {
todo!()
use crate::common::LineIter;
#[derive(Debug)]
struct BingoCard {
ticks: [[bool; 5]; 5],
mapping: HashMap<u8, (u8, u8)>,
}
pub fn part2(_input: &mut dyn Read) -> String {
todo!()
impl BingoCard {
pub fn cross(&mut self, num: u8) -> bool {
if let Some(&(x, y)) = self.mapping.get(&num) {
self.ticks[y as usize][x as usize] = true;
true
} else {
false
}
}
pub fn has_won(&self) -> bool {
// Check horizontal lines
if self.ticks.iter().any(|s| s.iter().all(|&b| b)) {
return true;
}
// Check vertical lines
(0..5).any(|x| (0..5).all(|y| self.ticks[y][x]))
// Diagonals do not count
}
pub fn remaining(&self) -> u32 {
self.mapping
.iter()
.filter_map(|(&num, &(x, y))| {
if self.ticks[y as usize][x as usize] {
None
} else {
Some(num as u32)
}
})
.sum()
}
}
fn read_input(input: &mut dyn Read) -> (Vec<u8>, Vec<BingoCard>) {
let mut reader = LineIter::new(input);
let numbers: Vec<u8> = reader
.next()
.unwrap()
.split(',')
.map(|num| num.parse().unwrap())
.collect();
let mut bingo_cards = Vec::new();
while reader.next().is_some() {
let mut mapping = HashMap::new();
for y in 0..5 {
reader
.next()
.unwrap()
.split(' ')
.filter_map(|s| if s.is_empty() { None } else { s.parse().ok() })
.enumerate()
.for_each(|(x, num)| {
mapping.insert(num, (x as u8, y));
});
}
let card = BingoCard {
mapping,
ticks: Default::default(),
};
bingo_cards.push(card);
}
(numbers, bingo_cards)
}
pub fn part1(input: &mut dyn Read) -> String {
let (numbers, mut bingo_cards) = read_input(input);
for number in numbers {
for card in &mut bingo_cards {
if card.cross(number) && card.has_won() {
return (number as u32 * card.remaining()).to_string();
}
}
}
panic!("None of the cards won")
}
pub fn part2(input: &mut dyn Read) -> String {
let (numbers, mut bingo_cards) = read_input(input);
for number in numbers {
bingo_cards.iter_mut().for_each(|card| {
card.cross(number);
});
if bingo_cards.len() == 1 && bingo_cards[0].cross(number) && bingo_cards[0].has_won() {
return (number as u32 * bingo_cards[0].remaining()).to_string();
} else {
bingo_cards.retain(|card| !card.has_won());
}
}
panic!("Not all cards won!")
}
#[cfg(test)]
mod tests {
use crate::test_implementation;
use super::*;
const SAMPLE: &[u8] = include_bytes!("samples/04.txt");
#[test]
fn sample_part1() {
test_implementation(part1, SAMPLE, 4512)
}
#[test]
fn sample_part2() {
test_implementation(part2, SAMPLE, 1924)
}
}

19
2021/src/samples/04.txt Normal file
View File

@@ -0,0 +1,19 @@
7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1
22 13 17 11 0
8 2 23 4 24
21 9 14 16 7
6 10 3 18 5
1 12 20 15 19
3 15 0 2 22
9 18 13 17 5
19 8 7 25 23
20 11 10 24 4
14 21 16 12 6
14 21 17 24 4
10 16 15 9 19
18 8 23 26 20
22 11 13 6 5
2 0 12 3 7