diff --git a/data/examples/05.txt b/data/examples/05.txt new file mode 100644 index 000000000..9d146d6 --- /dev/null +++ b/data/examples/05.txt @@ -0,0 +1,28 @@ +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 diff --git a/src/bin/05.rs b/src/bin/05.rs new file mode 100644 index 000000000..8bccef0 --- /dev/null +++ b/src/bin/05.rs @@ -0,0 +1,97 @@ +use std::cmp::Ordering; + +use hashbrown::HashSet; +use itertools::Itertools; + +#[derive(Debug)] +struct PageUpdates { + raw: Vec, + sorted: Vec, +} + +impl PageUpdates { + fn middle(&self) -> usize { + self.sorted[self.sorted.len() / 2] + } + + fn is_sorted(&self) -> bool { + self.raw == self.sorted + } +} + +fn parse_updates(input: &str) -> Vec { + let (page_orderings, updates) = input.split_once("\n\n").unwrap(); + + let mut ordering = HashSet::new(); + + for line in page_orderings.lines() { + let (a, b) = line.split_once('|').unwrap(); + let a = a.parse().unwrap(); + let b = b.parse().unwrap(); + ordering.insert((a, b)); + } + + let cmp = |&a: &usize, &b: &usize| { + if ordering.contains(&(a, b)) { + Ordering::Less + } else if ordering.contains(&(b, a)) { + Ordering::Greater + } else { + Ordering::Equal + } + }; + + let mut page_updates = vec![]; + for update in updates.lines() { + let raw = update + .split(',') + .filter_map(|x| x.parse().ok()) + .collect_vec(); + + let mut sorted = raw.clone(); + sorted.sort_by(cmp); + + page_updates.push(PageUpdates { raw, sorted }); + } + + page_updates +} + +pub fn part_one(input: &str) -> Option { + parse_updates(input) + .iter() + .filter(|pu| pu.is_sorted()) + .map(PageUpdates::middle) + .sum::() + .into() +} + +pub fn part_two(input: &str) -> Option { + parse_updates(input) + .iter() + .filter(|pu| !pu.is_sorted()) + .map(PageUpdates::middle) + .sum::() + .into() +} + +aoc::solution!(5); + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_part_one() { + assert_eq!( + part_one(&aoc::template::read_file("examples", 5)), + Some(143) + ); + } + #[test] + fn test_part_two() { + assert_eq!( + part_two(&aoc::template::read_file("examples", 5)), + Some(123) + ); + } +}