diff --git a/2023/day4/rust/Cargo.toml b/2023/day4/rust/Cargo.toml new file mode 100644 index 0000000..e4ddd6a --- /dev/null +++ b/2023/day4/rust/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "rust_2023_04" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +aoc = { path = "../../../common/rust" } diff --git a/2023/day4/rust/src/main.rs b/2023/day4/rust/src/main.rs new file mode 100644 index 0000000..be8001a --- /dev/null +++ b/2023/day4/rust/src/main.rs @@ -0,0 +1,69 @@ +#![warn(clippy::pedantic)] + +use std::{io::stdin, num::NonZeroU32}; + +#[derive(Debug, Clone, PartialEq, Eq)] +struct Card { + winning: Vec, + found: Vec, +} + +impl Card { + pub fn parse(s: &str) -> Self { + fn get_numbers(s: &str) -> Vec { + s.split(' ') + .filter(|s| !s.is_empty()) + .map(|n| n.parse().unwrap()) + .collect() + } + + let (_id, numbers) = s.split_once(": ").unwrap(); + let (winning, found) = numbers.split_once(" | ").unwrap(); + let winning = get_numbers(winning); + let found = get_numbers(found); + + Self { winning, found } + } + + pub fn num_matching(&self) -> usize { + self.found + .iter() + .filter(|n| self.winning.contains(n)) + .count() + } + + pub fn exp_score(&self) -> usize { + if let Some(matching) = NonZeroU32::new(u32::try_from(self.num_matching()).unwrap()) { + 2_usize.pow(matching.get() - 1) + } else { + 0 + } + } + + pub fn recursive_score(&self, previous: &[usize]) -> usize { + 1 + previous + .iter() + .rev() + .take(self.num_matching()) + .sum::() + } +} + +fn main() { + let cards: Vec = stdin().lines().map(|l| Card::parse(&l.unwrap())).collect(); + + println!("{}", cards.iter().map(Card::exp_score).sum::()); + + let recursive_score: usize = cards + .iter() + .rev() + .fold(Vec::new(), |mut previous, card| { + let score = card.recursive_score(&previous); + previous.push(score); + previous + }) + .iter() + .sum(); + + println!("{recursive_score}"); +} diff --git a/Cargo.lock b/Cargo.lock index 6448e9e..87af957 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -663,6 +663,13 @@ dependencies = [ "enum-map", ] +[[package]] +name = "rust_2023_04" +version = "0.1.0" +dependencies = [ + "aoc", +] + [[package]] name = "rust_2023_05" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index f4cf0d3..461b612 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,5 +29,6 @@ members = [ "2022/day18/rust", "2023/day1/rust", "2023/day2/rust", + "2023/day4/rust", "2023/day5/rust", ]