From 6394c755240fceb8986920dbb585eca7b8bda194 Mon Sep 17 00:00:00 2001 From: uku Date: Sat, 7 Dec 2024 15:22:57 +0100 Subject: [PATCH] feat(day5): init --- src/solutions/day_05.rs | 146 ++++++++++++++++++++++++++++++++++++++++ src/solutions/mod.rs | 2 + 2 files changed, 148 insertions(+) create mode 100644 src/solutions/day_05.rs diff --git a/src/solutions/day_05.rs b/src/solutions/day_05.rs new file mode 100644 index 0000000..711574a --- /dev/null +++ b/src/solutions/day_05.rs @@ -0,0 +1,146 @@ +use std::collections::{HashMap, HashSet}; + +use itertools::Itertools; + +use crate::common::{Answer, Solution}; + +pub struct Day05; + +impl Solution for Day05 { + fn name(&self) -> &'static str { + "Print Queue" + } + + fn part_a(&self, input: &str) -> Answer { + let (rules, input) = input.split_once("\n\n").unwrap(); + + let rules = rules + .lines() + .map(|l| l.split_once("|").unwrap()) + .map(|(a, b)| (a.parse::().unwrap(), b.parse::().unwrap())) + .into_grouping_map() + .collect::>(); + + let sum = input + .lines() + .map(|l| { + l.split(",") + .map(|n| n.parse::().unwrap()) + .collect::>() + }) + .filter(|nums| is_ordered(nums, &rules)) + .map(|nums| { + let middle = (nums.len() - 1) / 2; + nums[middle] + }) + .sum::(); + + Answer::Number(sum) + } + + fn part_b(&self, input: &str) -> Answer { + let (rules, input) = input.split_once("\n\n").unwrap(); + + let rules = rules + .lines() + .map(|l| l.split_once("|").unwrap()) + .map(|(a, b)| (a.parse::().unwrap(), b.parse::().unwrap())) + .into_grouping_map() + .collect::>(); + + let sum = input + .lines() + .map(|l| { + l.split(",") + .map(|n| n.parse::().unwrap()) + .collect::>() + }) + .filter(|nums| !is_ordered(nums, &rules)) + .map(|mut nums| { + while !is_ordered(&nums, &rules) { + for (i, n) in nums.clone().iter().enumerate() { + let Some(rules) = rules.get(n) else { + continue; + }; + + let first_invalid = nums + .iter() + .enumerate() + .take(i) + .filter(|(_, n)| rules.contains(n)) + .map(|(i2, _)| i2) + .next(); + + if let Some(i2) = first_invalid { + nums.swap(i, i2); + } + } + } + + nums + }) + .map(|nums| { + let middle = (nums.len() - 1) / 2; + nums[middle] + }) + .sum::(); + + Answer::Number(sum) + } +} + +fn is_ordered(nums: &[u64], rules: &HashMap>) -> bool { + nums.iter() + .enumerate() + .filter_map(|(i, n)| rules.get(n).map(|r| (i, r))) + .all(|(i, rules)| !nums.iter().take(i).any(|n| rules.contains(n))) +} + +#[cfg(test)] +mod test { + use super::Day05; + use crate::common::Solution; + + use indoc::indoc; + + const INPUT: &str = indoc! {" + 47|53 + 97|13 + 97|61 + 97|47 + 75|29 + 61|13 + 75|53 + 29|13 + 97|29 + 53|29 + 61|53 + 97|53 + 61|29 + 47|13 + 75|47 + 97|75 + 47|61 + 75|61 + 47|29 + 75|13 + 53|13 + + 75,47,61,53,29 + 97,61,53,29,13 + 75,29,13 + 75,97,47,61,53 + 61,13,29 + 97,13,75,29,47 + "}; + + #[test] + fn part_a() { + assert_eq!(Day05.part_a(INPUT), 143.into()); + } + + #[test] + fn part_b() { + assert_eq!(Day05.part_b(INPUT), 123.into()); + } +} diff --git a/src/solutions/mod.rs b/src/solutions/mod.rs index e27f88f..e9ac97d 100644 --- a/src/solutions/mod.rs +++ b/src/solutions/mod.rs @@ -4,10 +4,12 @@ mod day_01; mod day_02; mod day_03; mod day_04; +mod day_05; pub const SOLUTIONS: &[&dyn Solution] = &[ &day_01::Day01, &day_02::Day02, &day_03::Day03, &day_04::Day04, + &day_05::Day05, ];