2025/day-05: Solve part 2

This commit is contained in:
SebastianStork 2025-12-05 19:18:52 +01:00
parent 2786c75a97
commit 5929ef6b97
Signed by: SebastianStork
SSH key fingerprint: SHA256:iEM011ogNMG1q8+U500adGu/9rpPuZ2KnFtbdLeqTiI

View file

@ -6,7 +6,7 @@ struct Range {
} }
impl Range { impl Range {
fn new(start: u64, end: u64) -> Range { fn new(start: u64, end: u64) -> Self {
Range { start, end } Range { start, end }
} }
@ -14,7 +14,11 @@ impl Range {
num >= self.start && num <= self.end num >= self.start && num <= self.end
} }
fn expand(&mut self, overlap: &Range) { fn overlaps(&self, other: &Range) -> bool {
self.contains(other.start) || self.contains(other.end)
}
fn merge_with(&mut self, overlap: &Range) {
if overlap.start < self.start { if overlap.start < self.start {
self.start = overlap.start; self.start = overlap.start;
} }
@ -22,16 +26,21 @@ impl Range {
self.end = overlap.end; self.end = overlap.end;
} }
} }
fn length(&self) -> u64 {
self.end - self.start + 1
}
} }
fn main() { fn main() {
let (ranges, available_ids) = parse_input(&fs::read_to_string("../../inputs/05.txt").unwrap()); let (ranges, available_ids) = parse_input(&fs::read_to_string("../../inputs/05.txt").unwrap());
let ranges = compress(ranges); let ranges = merge_overlapping_ranges(ranges);
println!( println!(
"How many of the available ingredient IDs are fresh? {}", "Number of available IDs in ranges: {}",
number_of_available_ids_in_rages(available_ids, ranges) count_available_ids_in_ranges(available_ids, &ranges)
); );
println!("Number of IDs in ranges: {}", count_ids_in_ranges(&ranges));
} }
fn parse_input(contents: &str) -> (Vec<Range>, Vec<u64>) { fn parse_input(contents: &str) -> (Vec<Range>, Vec<u64>) {
@ -50,23 +59,17 @@ fn parse_input(contents: &str) -> (Vec<Range>, Vec<u64>) {
(ranges, available_ids) (ranges, available_ids)
} }
fn compress(mut ranges: Vec<Range>) -> Vec<Range> { fn merge_overlapping_ranges(mut ranges: Vec<Range>) -> Vec<Range> {
ranges.sort_by_key(|range| range.start);
let mut compressed_ranges = vec![ranges.remove(0)]; let mut compressed_ranges = vec![ranges.remove(0)];
for range in ranges { for range in ranges {
let mut is_integrated = false; let previous = compressed_ranges.last_mut().unwrap();
for compressed_range in &mut compressed_ranges {
if compressed_range.contains(range.start) && compressed_range.contains(range.end) { if previous.overlaps(&range) {
is_integrated = true; previous.merge_with(&range);
break; } else {
}
if compressed_range.contains(range.start) || compressed_range.contains(range.end) {
compressed_range.expand(&range);
is_integrated = true;
break;
}
}
if !is_integrated {
compressed_ranges.push(range); compressed_ranges.push(range);
} }
} }
@ -74,13 +77,17 @@ fn compress(mut ranges: Vec<Range>) -> Vec<Range> {
compressed_ranges compressed_ranges
} }
fn number_of_available_ids_in_rages(available_ids: Vec<u64>, ranges: Vec<Range>) -> usize { fn count_available_ids_in_ranges(available_ids: Vec<u64>, ranges: &[Range]) -> usize {
available_ids available_ids
.iter() .iter()
.filter(|id| ranges.iter().any(|range| range.contains(**id))) .filter(|id| ranges.iter().any(|range| range.contains(**id)))
.count() .count()
} }
fn count_ids_in_ranges(ranges: &[Range]) -> u64 {
ranges.iter().map(|range| range.length()).sum()
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
@ -102,8 +109,16 @@ mod tests {
#[test] #[test]
fn test_part1() { fn test_part1() {
let (ranges, available_ids) = parse_input(TEST_INPUT); let (ranges, available_ids) = parse_input(TEST_INPUT);
let ranges = compress(ranges); let ranges = merge_overlapping_ranges(ranges);
assert_eq!(number_of_available_ids_in_rages(available_ids, ranges), 3); assert_eq!(count_available_ids_in_ranges(available_ids, &ranges), 3);
}
#[test]
fn test_part2() {
let (ranges, _) = parse_input(TEST_INPUT);
let ranges = merge_overlapping_ranges(merge_overlapping_ranges(ranges));
assert_eq!(count_ids_in_ranges(&ranges), 14);
} }
} }