diff --git a/AoC_2025/src/days/day05.rs b/AoC_2025/src/days/day05.rs index dbaef96..d9cd3c5 100644 --- a/AoC_2025/src/days/day05.rs +++ b/AoC_2025/src/days/day05.rs @@ -1,4 +1,4 @@ -use std::collections::BTreeSet; +use std::cmp::max; use crate::days::Solution; @@ -50,6 +50,64 @@ impl Solution for Day05 { ingredients: _, }: &Self::Input, ) -> usize { - 0 + reduce_ranges(&ranges).iter().map(|(x, y)| y + 1 - x).sum() } } + +/// Reduce recursively a Vec of ranges to a Vec of non-overlapping ranges +fn reduce_ranges(input: &Vec<(usize, usize)>) -> Vec<(usize, usize)> { + let mut input = input.clone(); + input.sort(); + let mut input = group_overlapping_ranges(&input); + + input + .iter_mut() + .flat_map(|g| { + if g.len() > 1 { + reduce_ranges( + &g.chunks(2) + .flat_map(|w| { + if w.len() == 2 { + simplify_ranges(w[0], w[1]) + } else { + vec![w[0]] + } + }) + .collect(), + ) + } else { + g.to_owned() + } + }) + .collect() +} + +/// Simplify two ordered ranges (p1 <= p2) to give an equivalent Vec of disctinct ranges +fn simplify_ranges((x1, y1): (usize, usize), (x2, y2): (usize, usize)) -> Vec<(usize, usize)> { + if y1 < x2 { + vec![(x1, y1), (x2, y2)] + } else if (x1, y1) == (x2, y2) { + vec![(x1, y1)] + } else if y1 == x2 { + vec![(x1, y2)] + } else { + vec![(x1, max(y1, y2))] + } +} + +/// Group a Vec of ranges by overlapping ranges +fn group_overlapping_ranges(ranges: &Vec<(usize, usize)>) -> Vec> { + ranges + .iter() + .fold((vec![], None), |(mut v, state), &(x, y)| { + if state.is_none_or(|(_, sy)| sy < x) { + // Create new range group + v.push(vec![(x, y)]); + (v, Some((x, y))) + } else { + v.last_mut().unwrap().push((x, y)); + (v, Some((x, max(y, state.unwrap().1)))) + } + }) + .0 +}