Advent of Code solutions

Day 5

bwc9876.dev 796138a9 a668d38d

verified
+88 -7
+16 -1
utils/src/range.rs
··· 51 51 /// ``` 52 52 /// 53 53 pub fn contains_range(&self, other: &Self) -> bool { 54 - self.start <= other.start && other.end < self.end 54 + self.start <= other.start && other.end <= self.end 55 + } 56 + 57 + /// Merge this range with another. If the ranges do not intersect, [None] is returned. 58 + pub fn merge(&self, other: &Self) -> Option<Self> { 59 + if self.contains_range(other) { 60 + Some(*self) 61 + } else if other.contains_range(self) { 62 + Some(*other) 63 + } else if self.contains(&other.start) || self.end == other.start { 64 + Some(Self::new(self.start, other.end)) 65 + } else if self.contains(&other.end) || other.end == self.start { 66 + Some(Self::new(other.start, self.end)) 67 + } else { 68 + None 69 + } 55 70 } 56 71 57 72 /// Split the range at the given value.
+50 -6
years/2025/src/day_5.rs
··· 1 - 2 1 use advent_core::{Day, day_stuff, ex_for_day}; 2 + use utils::range::BetterRange; 3 3 4 4 pub struct Day5; 5 5 6 6 impl Day for Day5 { 7 + day_stuff!(5, "3", "14", (Vec<BetterRange<usize>>, Vec<usize>)); 7 8 8 - day_stuff!(5, "", ""); 9 + fn part_1((ranges, ids): Self::Input) -> Option<String> { 10 + let ans = ids 11 + .into_iter() 12 + .filter(|id| ranges.iter().any(|range| range.contains(id))) 13 + .count(); 9 14 10 - fn part_1(_input: Self::Input) -> Option<String> { 11 - None 15 + Some(ans.to_string()) 12 16 } 13 17 14 - fn part_2(_input: Self::Input) -> Option<String> { 15 - None 18 + fn part_2((mut ranges, _): Self::Input) -> Option<String> { 19 + ranges.sort_by(|a, b| a.start.cmp(&b.start).then(a.end.cmp(&b.end))); 20 + 21 + let mut new_ranges = Vec::with_capacity(ranges.len()); 22 + 23 + for range in ranges { 24 + let mut merged = false; 25 + 26 + for new_range in new_ranges.iter_mut() { 27 + if let Some(merged_range) = range.merge(new_range) { 28 + merged = true; 29 + *new_range = merged_range; 30 + break; 31 + } 32 + } 33 + 34 + if !merged { 35 + new_ranges.push(range); 36 + } 37 + } 38 + 39 + let ans = new_ranges 40 + .into_iter() 41 + .map(|range| range.end - range.start) 42 + .sum::<usize>(); 43 + 44 + Some(ans.to_string()) 45 + } 46 + 47 + fn parse_input(input: &str) -> Self::Input { 48 + let (ranges, ids) = input.split_once("\n\n").unwrap(); 49 + 50 + ( 51 + ranges 52 + .lines() 53 + .map(|l| { 54 + let (lower, upper) = l.split_once('-').unwrap(); 55 + BetterRange::new(lower.parse().unwrap(), upper.parse::<usize>().unwrap() + 1) 56 + }) 57 + .collect(), 58 + ids.lines().map(|l| l.parse().unwrap()).collect(), 59 + ) 16 60 } 17 61 }
+11
years/2025/src/examples/day_5/1.txt
··· 1 + 3-5 2 + 10-14 3 + 16-20 4 + 12-18 5 + 6 + 1 7 + 5 8 + 8 9 + 11 10 + 17 11 + 32
+11
years/2025/src/examples/day_5/2.txt
··· 1 + 3-5 2 + 10-14 3 + 16-20 4 + 12-18 5 + 6 + 1 7 + 5 8 + 8 9 + 11 10 + 17 11 + 32