diff options
Diffstat (limited to '2023/src')
-rw-r--r-- | 2023/src/bin/day_4.rs | 91 |
1 files changed, 82 insertions, 9 deletions
diff --git a/2023/src/bin/day_4.rs b/2023/src/bin/day_4.rs index b3a610b..7f5af6b 100644 --- a/2023/src/bin/day_4.rs +++ b/2023/src/bin/day_4.rs @@ -1,19 +1,92 @@ -use nom::IResult; -use std::fs; +use nom::{ + bytes::complete::tag, + character::complete::{line_ending, space1, u32 as nom_u32}, + combinator::map, + multi::separated_list1, + sequence::tuple, + IResult, +}; +use std::{collections::BTreeSet, fs}; fn main() -> Result<(), Box<dyn std::error::Error>> { - let input = fs::read_to_string("inputs/day_2.txt")?; - let parsed = Example::parser(&input).unwrap().1; - dbg!(&parsed); + let input = fs::read_to_string("inputs/day_4.txt")?; + let parsed = Scratchcards::parser(&input).unwrap().1; + dbg!(&parsed.points()); + dbg!(&parsed.scratchcard_explosion_sum()); Ok(()) } #[derive(Debug)] -struct Example; +struct Scratchcards(Vec<Scratchcard>); -impl Example { - fn parser(_input: &str) -> IResult<&str, Self> { - todo!() +#[derive(Debug)] +struct Scratchcard { + winning: BTreeSet<u32>, + owned: BTreeSet<u32>, +} + +impl Scratchcards { + fn parser(input: &str) -> IResult<&str, Self> { + map( + separated_list1(line_ending, Scratchcard::parser), + Scratchcards, + )(input) + } + + fn points(&self) -> usize { + self.0.iter().map(|card| card.points()).sum() + } + + fn scratchcard_explosion_sum(&self) -> u64 { + let mut scratchcard_pile = vec![1_u64.into(); self.0.len()]; + + for i in 0..scratchcard_pile.len() { + let points = self.0[i].winning_numbers(); + let new_scratchcards: u64 = scratchcard_pile[i]; + for offset in 0..points { + if let Some(pile) = scratchcard_pile.get_mut(i + 1 + offset) { + *pile += new_scratchcards; + } + } + } + + scratchcard_pile.into_iter().sum() + } +} + +impl Scratchcard { + fn parser(input: &str) -> IResult<&str, Self> { + map( + tuple(( + tag("Card"), + space1, + nom_u32, + tag(":"), + space1, + separated_list1(space1, nom_u32), + space1, + tag("|"), + space1, + separated_list1(space1, nom_u32), + )), + |(_, _, _, _, _, winning, _, _, _, owned)| Scratchcard { + winning: winning.into_iter().collect(), + owned: owned.into_iter().collect(), + }, + )(input) + } + + fn winning_numbers(&self) -> usize { + self.winning.intersection(&self.owned).count() + } + + fn points(&self) -> usize { + let winning_numbers = self.winning_numbers(); + if winning_numbers > 0 { + 2_usize.pow(winning_numbers as u32 - 1) + } else { + 0 + } } } |