From: Jack Kinsey Date: Fri, 6 Dec 2024 03:44:37 +0000 (-0500) Subject: Complete day 5 X-Git-Url: http://git.jkinsey.net/?a=commitdiff_plain;h=af2fa1ffddc96b875b2322cfa708a2aa1e5e278d;p=adventofcode2024.git Complete day 5 --- diff --git a/src/day05.rs b/src/day05.rs new file mode 100644 index 0000000..efbb7b2 --- /dev/null +++ b/src/day05.rs @@ -0,0 +1,155 @@ +use std::collections::{HashMap, HashSet}; +use std::rc::Rc; + +fn input() -> &'static str { + include_str!("../input/day05.txt") +} + +type PageSet = HashSet; +type PageRel = HashMap; + +#[derive(Debug)] +struct Page { + num: u8, + rel: Rc, +} + +impl PartialEq for Page { + fn eq(&self, other: &Self) -> bool { + self.num == other.num + } +} + +impl Eq for Page {} + +impl PartialOrd for Page { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Page { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + if self == other { + std::cmp::Ordering::Equal + } else if self + .rel + .get(&self.num) + .unwrap_or_else(|| panic!("{:?}", self)) + .contains(&other.num) + { + std::cmp::Ordering::Less + } else { + std::cmp::Ordering::Greater + } + } +} + +fn parse(input: &str) -> Vec> { + let [ord, runs] = input.split("\n\n").collect::>()[..] else { + panic!() + }; + + let mut rel = PageRel::new(); + + let rels: Vec> = ord + .split_terminator("\n") + .map(|s| s.split("|").map(|n| n.parse().unwrap()).collect::>()) + .collect(); + + for pair in rels { + let [l, r] = pair[..] else { panic!() }; + rel.entry(r).or_default(); + rel.entry(l).or_default().insert(r); + } + + let relf = Rc::new(rel); + + let pages: Vec> = runs + .split_terminator("\n") + .map(|s| { + s.split(",") + .map(|n| Page { + num: n.parse().unwrap(), + rel: Rc::clone(&relf), + }) + .collect() + }) + .collect(); + + pages +} + +fn get_middle(run: &[Page]) -> u8 { + run[(run.len() + 1) / 2].num +} + +pub fn part1() { + let pages = parse(input()); + let n: u32 = pages + .iter() + .filter(|p| p.is_sorted()) + .map(|p| -> u32 { get_middle(p).into() }) + .sum(); + println!("Day 5 Part 1: {}", n); +} + +pub fn part2() { + let mut pages = parse(input()); + let n: u32 = pages + .iter_mut() + .filter(|p| !p.is_sorted()) + .map(|p| -> u32 { + p.sort(); + get_middle(p).into() + }) + .sum(); + println!("Day 5 Part 2: {}", n); +} + +#[cfg(test)] +mod test { + use super::*; + + const INPUT_STR: &str = concat!( + "47|53\n", + "97|13\n", + "97|61\n", + "97|47\n", + "75|29\n", + "61|13\n", + "75|53\n", + "29|13\n", + "97|29\n", + "53|29\n", + "61|53\n", + "97|53\n", + "61|29\n", + "47|13\n", + "75|47\n", + "97|75\n", + "47|61\n", + "75|61\n", + "47|29\n", + "75|13\n", + "53|13\n", + "\n", + "75,47,61,53,29\n", + "97,61,53,29,13\n", + "75,29,13\n", + "75,97,47,61,53\n", + "61,13,29\n", + "97,13,75,29,47\n", + ); + + #[test] + fn test_page_sort() { + let pages = parse(INPUT_STR); + assert!(&pages[0].is_sorted()); + assert!(&pages[1].is_sorted()); + assert!(&pages[2].is_sorted()); + assert!(!&pages[3].is_sorted()); + assert!(!&pages[4].is_sorted()); + assert!(!&pages[5].is_sorted()); + } +} diff --git a/src/main.rs b/src/main.rs index ffc622c..c57bf00 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,7 @@ pub mod day01; pub mod day02; pub mod day03; pub mod day04; -// pub mod day05; +pub mod day05; // pub mod day06; // pub mod day07; // pub mod day08; @@ -26,12 +26,12 @@ pub mod day04; type Part = fn(); -const DAYS: [(Part, Part); 4] = [ +const DAYS: [(Part, Part); 5] = [ (day01::part1 as fn(), day01::part2 as fn()), (day02::part1 as fn(), day02::part2 as fn()), (day03::part1 as fn(), day03::part2 as fn()), (day04::part1 as fn(), day04::part2 as fn()), - // (day05::part1 as fn(), day05::part2 as fn()), + (day05::part1 as fn(), day05::part2 as fn()), // (day06::part1 as fn(), day06::part2 as fn()), // (day07::part1 as fn(), day07::part2 as fn()), // (day08::part1 as fn(), day08::part2 as fn()),