diff --git a/src/main.rs b/src/main.rs index 450f27f..35d09bd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -203,13 +203,92 @@ mod day4 { } } -fn main() { - // day1::task1(); - // day1::task1(); - // day2::task1(); - // day2::task2(); - // day3::task1(); - // day3::task2(); - day4::task1(); - day4::task2(); +mod day5 { + use std::{ + cmp::Ordering, + collections::{HashMap, HashSet}, + }; + + use itertools::Itertools; + + type Rules = HashMap>; + + fn parse_rules<'a>(lines: &mut impl Iterator) -> Rules { + let mut rules: Rules = HashMap::new(); + for rule in lines.by_ref().take_while(|s| !s.is_empty()) { + let vals = rule.split_once('|').unwrap(); + let (before, after) = (vals.0.parse().unwrap(), vals.1.parse().unwrap()); + rules.entry(before).or_default().insert(after); + } + rules + } + + fn parse_updates<'a>( + lines: impl Iterator + 'a, + ) -> impl Iterator> + 'a { + lines.map(|line| { + line.trim() + .split(',') + .map(|num| num.parse::().unwrap()) + .collect_vec() + }) + } + + fn check_update(update: &[i32], rules: &Rules) -> bool { + for (i, val) in update.iter().enumerate() { + let Some(local_rules) = rules.get(val) else { + continue; + }; + if update[..i].iter().any(|elem| local_rules.contains(elem)) { + return false; + } + } + true + } + + #[allow(dead_code)] + pub fn task1() { + let data = std::fs::read_to_string("input.txt").unwrap(); + let mut lines = data.lines(); + let rules = parse_rules(&mut lines); + let result: i32 = parse_updates(lines) + .filter(|u| check_update(u, &rules)) + .map(|u| u[u.len() / 2]) + .sum(); + println!("{result}"); + } + + fn compare(a: i32, b: i32, rules: &Rules) -> Ordering { + if let Some(rule) = rules.get(&a) { + if rule.contains(&b) { + return Ordering::Less; + } + } + if let Some(rule) = rules.get(&b) { + if rule.contains(&a) { + return Ordering::Greater; + } + } + Ordering::Equal + } + + #[allow(dead_code)] + pub fn task2() { + let data = std::fs::read_to_string("input.txt").unwrap(); + let mut lines = data.lines(); + let rules = parse_rules(&mut lines); + let result: i32 = parse_updates(lines) + .filter(|u| !check_update(u, &rules)) + .map(|mut u| { + u.sort_unstable_by(|a, b| compare(*a, *b, &rules)); + u[u.len() / 2] + }) + .sum(); + println!("{result}"); + } +} + +fn main() { + day5::task1(); + day5::task2(); }