From 608aaf9a5cf769ced7e02a4ce2cc27beba6dcbba Mon Sep 17 00:00:00 2001 From: Toby Vincent Date: Mon, 4 Dec 2023 19:06:10 -0600 Subject: feat: impl day 4 --- src/day_04.rs | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 +- src/main.rs | 3 +- 3 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 src/day_04.rs (limited to 'src') diff --git a/src/day_04.rs b/src/day_04.rs new file mode 100644 index 0000000..77559e2 --- /dev/null +++ b/src/day_04.rs @@ -0,0 +1,110 @@ +use crate::{Problem, Solution}; + +pub struct Day04; + +impl Problem for Day04 { + const DAY: u8 = 4; + + const INPUT: &'static str = include_str!("../input/day_04.txt"); +} + +impl Solution for Day04 { + type Answer1 = usize; + + type Answer2 = usize; + + fn part_1(input: &str) -> anyhow::Result { + let scores = input + .trim() + .split('\n') + .map(parse_score) + .collect::, _>>()?; + + Ok(scores + .into_iter() + .filter(|n| n > &0) + .map(|n| 2usize.pow(n as u32 - 1)) + .sum()) + } + + fn part_2(input: &str) -> anyhow::Result { + let scores = input + .trim() + .split('\n') + .map(parse_score) + .collect::, _>>()?; + + let cards = &mut vec![0usize; scores.len()]; + + for card in 0..scores.len() { + add_copy(cards, &scores, card) + } + + Ok(cards.iter().sum()) + } +} + +fn add_copy(cards: &mut Vec, scores: &[usize], card: usize) { + cards[card] += 1; + + for card in card + 1..cards.len().min(card + scores[card] + 1) { + add_copy(cards, scores, card); + } +} + +fn parse_score(s: &str) -> anyhow::Result { + let (winning, numbers) = s + .trim() + .split_once(':') + .ok_or(anyhow::format_err!("Invalid card format: {s}"))? + .1 + .trim() + .split_once('|') + .ok_or(anyhow::format_err!("Invalid card format: {s}"))?; + + let winning_set = winning + .split_whitespace() + .map(std::str::FromStr::from_str) + .collect::, _>>()?; + + Ok(numbers + .split_whitespace() + .map(std::str::FromStr::from_str) + .collect::, _>>()? + .into_iter() + .filter(|n| winning_set.contains(n)) + .count()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part_1() -> anyhow::Result<()> { + const INPUT: &str = indoc::indoc! {" + Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53 + Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19 + Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1 + Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83 + Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36 + Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11 + "}; + + Ok(assert_eq!(13, Day04::part_1(INPUT)?)) + } + + #[test] + fn test_part_2() -> anyhow::Result<()> { + const INPUT: &str = indoc::indoc! {" + Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53 + Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19 + Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1 + Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83 + Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36 + Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11 + "}; + + Ok(assert_eq!(30, Day04::part_2(INPUT)?)) + } +} diff --git a/src/lib.rs b/src/lib.rs index 42df819..71a3568 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,9 @@ #![feature(iterator_try_collect)] - + pub mod day_01; pub mod day_02; pub mod day_03; +pub mod day_04; pub trait Problem { const DAY: u8; diff --git a/src/main.rs b/src/main.rs index 7ac9cfa..3f47fac 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,10 @@ -use aoc_2023::{day_01::Day01, day_02::Day02, day_03::Day03, Solution}; +use aoc_2023::{day_01::Day01, day_02::Day02, day_03::Day03, day_04::Day04, Solution}; fn main() -> anyhow::Result<()> { Day01::solve()?; Day02::solve()?; Day03::solve()?; + Day04::solve()?; Ok(()) } -- cgit v1.2.3-70-g09d2