From 73765e857aad685ab8fc3bab451bc03395e94902 Mon Sep 17 00:00:00 2001 From: Keenan Tims Date: Fri, 5 Dec 2025 01:09:32 -0800 Subject: [PATCH] day5: bugfixes for rangeset --- src/day5.rs | 64 +++++++++++++++++++++++++++-------------------------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/src/day5.rs b/src/day5.rs index a2f6131..50958e0 100644 --- a/src/day5.rs +++ b/src/day5.rs @@ -1,4 +1,4 @@ -use std::cmp::{max, min}; +use std::cmp::max; use std::fmt::Debug; use std::ops::RangeInclusive; @@ -43,45 +43,47 @@ impl RangeSet { Self { ranges: Vec::new() } } fn simplify(&mut self) { - // sort the ranges by start if self.ranges.len() < 2 { return; } let mut modified = true; while modified { - let mut new_ranges = Vec::new(); modified = false; + // sort the ranges by start self.ranges.sort_by_key(|s| s.start); - for chunk in self.ranges.chunks(2) { - if chunk.len() == 1 { - new_ranges.push(chunk[0].clone()); - continue; + let mut new_ranges = Vec::new(); + let mut pos = 1; + + while pos <= self.ranges.len() { + // part of a disgusting hack to avoid skipping or double adding at the end + if pos == self.ranges.len() { + pos -= 1; } - let (l, r) = (&chunk[0], &chunk[1]); + let (l, r) = (&self.ranges[pos - 1], &self.ranges[pos]); + if r.start <= l.end + 1 { modified = true; - new_ranges.push((min(r.start, l.start), max(l.end, r.end)).into()) - } else { - new_ranges.push(l.clone()); - new_ranges.push(r.clone()); - } - } - if !self.ranges.len().is_multiple_of(2) && new_ranges.len() >= 2 { - let (l, r) = (new_ranges.pop().unwrap(), new_ranges.pop().unwrap()); - if r.start <= l.end + 1 && r.end >= l.start - 1 { - modified = true; - new_ranges.push((min(r.start, l.start), max(l.end, r.end)).into()) + new_ranges.push((l.start, max(l.end, r.end)).into()); + // if we merged, skip checking the next range to avoid double-adding it + // this screws us up at the very end, so need the disgusting hack above + pos += 2; + } else if pos < self.ranges.len() - 1 { + // keep only the lhs if we didn't merge + new_ranges.push(l.clone()); + pos += 1; } else { + // at the end, keep both sides, otherwise the rhs gets excluded (if it didn't merge) new_ranges.push(l.clone()); new_ranges.push(r.clone()); + pos += 2; } } + self.ranges = new_ranges; } } fn add(&mut self, s: Span) { self.ranges.push(s); - self.simplify() } } @@ -111,6 +113,15 @@ fn parse(input: &str) -> Database { } } +#[aoc(day5, part1)] +fn part1(input: &Database) -> u64 { + input + .available_ingredients + .iter() + .filter(|i| input.fresh_ingredients.iter().any(|r| r.contains(i))) + .count() as u64 +} + #[aoc_generator(day5, part2)] fn parse2(input: &str) -> Database2 { let mut fresh_ingredients = Vec::new(); @@ -124,22 +135,13 @@ fn parse2(input: &str) -> Database2 { Database2 { fresh_ingredients } } -#[aoc(day5, part1)] -fn part1(input: &Database) -> u64 { - input - .available_ingredients - .iter() - .filter(|i| input.fresh_ingredients.iter().any(|r| r.contains(i))) - .count() as u64 -} - #[aoc(day5, part2)] fn part2(input: &Database2) -> u64 { let mut all_ingredients = RangeSet::new(); for r in &input.fresh_ingredients { - all_ingredients.add(r.clone()) + all_ingredients.add(r.clone()); } - + all_ingredients.simplify(); all_ingredients.ranges.iter().map(|r| r.len()).sum::() }