From 00793ab967380d60e2760bc0ba6782cf4ce4a4a6 Mon Sep 17 00:00:00 2001 From: Rh4096 Date: Thu, 5 Dec 2024 22:49:46 +0700 Subject: [PATCH] Day 5 --- src/main.rs | 4 +- src/solutions/day_5.rs | 92 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 61f92a8..3fd55f4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,7 @@ -use aoc2024::solutions::{day_4::AocDayFourSolution, AocSolution}; +use aoc2024::solutions::{day_5::AocDayFiveSolution, AocSolution}; fn main() { - let sol = AocDayFourSolution; + let sol = AocDayFiveSolution; println!("p1: {}\np2: {}", sol.part_one(), sol.part_two()) } diff --git a/src/solutions/day_5.rs b/src/solutions/day_5.rs index e69de29..8315e0d 100644 --- a/src/solutions/day_5.rs +++ b/src/solutions/day_5.rs @@ -0,0 +1,92 @@ +use std::{cmp::Ordering, collections::HashMap}; + +use super::AocSolution; + +#[derive(Debug)] +struct RuleChecker { + rules: HashMap>, + prints: Vec>, +} + +impl RuleChecker { + fn new(src: &str, prints_src: &str) -> Self { + Self { + rules: src + .lines() + .filter_map(|l| l.split_once('|')) + .filter_map( + |(a, b)| match (a.parse::().ok(), b.parse::().ok()) { + (Some(a), Some(b)) => Some((a, b)), + _ => None, + }, + ) + .fold(HashMap::new(), |mut map, (v, k)| { + let entry = map.entry(k).or_default(); + entry.push(v); + map + }), + prints: prints_src + .lines() + .map(|l| l.split(',').filter_map(|n| n.parse::().ok()).collect()) + .collect(), + } + } + + fn validate_print(&self, print: &[u8]) -> u8 { + if print.is_sorted_by(|a, b| self.rules.get(b).is_none_or(|v| v.contains(a))) { + print[print.len() / 2] + } else { + 0 + } + } + + fn compute_validated_print(&self) -> u64 { + let mut tmp = 0; + for print in &self.prints { + tmp += self.validate_print(print) as u64; + } + + tmp + } + + fn compute_invalid_print(&mut self) -> u64 { + let mut tmp = 0; + for print in self.prints.iter_mut() { + if !print.is_sorted_by(|a, b| self.rules.get(b).is_none_or(|v| v.contains(a))) { + print.sort_by(|a, b| { + if self.rules.get(a).is_none_or(|v| v.contains(b)) { + Ordering::Less + } else if self.rules.get(b).is_none_or(|v| v.contains(a)) { + Ordering::Greater + } else { + Ordering::Equal + } + }); + + tmp += print[print.len() / 2] as u64; + } + } + + tmp + } +} + +#[derive(Clone, Copy)] +pub struct AocDayFiveSolution; + +impl AocSolution for AocDayFiveSolution { + type Output = u64; + const INPUT: &str = include_str!("../../input/day5.txt"); + + fn part_one(&self) -> Self::Output { + let (rules, prints) = Self::INPUT.split_once("\r\n\r\n").unwrap_or(("", "")); + let checker = RuleChecker::new(rules, prints); + checker.compute_validated_print() + } + + fn part_two(&self) -> Self::Output { + let (rules, prints) = Self::INPUT.split_once("\r\n\r\n").unwrap_or(("", "")); + let mut checker = RuleChecker::new(rules, prints); + checker.compute_invalid_print() + } +}