From 2786c75a974cd19639f23000a622a572c3fc017a Mon Sep 17 00:00:00 2001 From: SebastianStork Date: Fri, 5 Dec 2025 11:41:41 +0100 Subject: [PATCH 1/2] 2025/day-01: Solve part 1 --- 2025/rust/day-05/Cargo.lock | 7 +++ 2025/rust/day-05/Cargo.toml | 6 ++ 2025/rust/day-05/src/main.rs | 109 +++++++++++++++++++++++++++++++++++ flake.lock | 6 +- 4 files changed, 125 insertions(+), 3 deletions(-) create mode 100644 2025/rust/day-05/Cargo.lock create mode 100644 2025/rust/day-05/Cargo.toml create mode 100644 2025/rust/day-05/src/main.rs diff --git a/2025/rust/day-05/Cargo.lock b/2025/rust/day-05/Cargo.lock new file mode 100644 index 0000000..992643d --- /dev/null +++ b/2025/rust/day-05/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "day-05" +version = "0.1.0" diff --git a/2025/rust/day-05/Cargo.toml b/2025/rust/day-05/Cargo.toml new file mode 100644 index 0000000..0c3df26 --- /dev/null +++ b/2025/rust/day-05/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "day-05" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/2025/rust/day-05/src/main.rs b/2025/rust/day-05/src/main.rs new file mode 100644 index 0000000..46c51e1 --- /dev/null +++ b/2025/rust/day-05/src/main.rs @@ -0,0 +1,109 @@ +use std::fs; + +struct Range { + start: u64, + end: u64, +} + +impl Range { + fn new(start: u64, end: u64) -> Range { + Range { start, end } + } + + fn contains(&self, num: u64) -> bool { + num >= self.start && num <= self.end + } + + fn expand(&mut self, overlap: &Range) { + if overlap.start < self.start { + self.start = overlap.start; + } + if overlap.end > self.end { + self.end = overlap.end; + } + } +} + +fn main() { + let (ranges, available_ids) = parse_input(&fs::read_to_string("../../inputs/05.txt").unwrap()); + let ranges = compress(ranges); + + println!( + "How many of the available ingredient IDs are fresh? {}", + number_of_available_ids_in_rages(available_ids, ranges) + ); +} + +fn parse_input(contents: &str) -> (Vec, Vec) { + let (ranges, available_ids) = contents.trim().split_once("\n\n").unwrap(); + + let ranges: Vec = ranges + .lines() + .map(|line| line.split_once("-").unwrap()) + .map(|(start, end)| Range::new(start.parse().unwrap(), end.parse().unwrap())) + .collect(); + let available_ids: Vec = available_ids + .lines() + .map(|line| line.parse().unwrap()) + .collect(); + + (ranges, available_ids) +} + +fn compress(mut ranges: Vec) -> Vec { + let mut compressed_ranges = vec![ranges.remove(0)]; + + for range in ranges { + let mut is_integrated = false; + for compressed_range in &mut compressed_ranges { + if compressed_range.contains(range.start) && compressed_range.contains(range.end) { + is_integrated = true; + break; + } + 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 +} + +fn number_of_available_ids_in_rages(available_ids: Vec, ranges: Vec) -> usize { + available_ids + .iter() + .filter(|id| ranges.iter().any(|range| range.contains(**id))) + .count() +} + +#[cfg(test)] +mod tests { + use super::*; + + const TEST_INPUT: &str = " +3-5 +10-14 +16-20 +12-18 + +1 +5 +8 +11 +17 +32 +"; + + #[test] + fn test_part1() { + let (ranges, available_ids) = parse_input(TEST_INPUT); + let ranges = compress(ranges); + + assert_eq!(number_of_available_ids_in_rages(available_ids, ranges), 3); + } +} diff --git a/flake.lock b/flake.lock index ec6ecaf..675648d 100644 --- a/flake.lock +++ b/flake.lock @@ -3,10 +3,10 @@ "inputs": { "flake": false, "locked": { - "lastModified": 1764840758, - "narHash": "sha256-GTN8SBnhvv6t2oDS1H85xcYAhafy8mpUQWSrCErhtgw=", + "lastModified": 1764926544, + "narHash": "sha256-xIkgV9KrBel6Qwy673iMmmggFGZ9Zz93Hd/lGhRyHRM=", "ref": "refs/heads/main", - "rev": "415a59297c64d0448d22975ca5ad3d8ef064c9f0", + "rev": "27de1eaccb499f25dca8f3505b4c4f42a8e35514", "shallow": true, "type": "git", "url": "ssh://git@github.com/SebastianStork/advent-of-code-inputs.git" From 5929ef6b973acf4c4ab0de25f54b8b012e9afc74 Mon Sep 17 00:00:00 2001 From: SebastianStork Date: Fri, 5 Dec 2025 19:18:52 +0100 Subject: [PATCH 2/2] 2025/day-05: Solve part 2 --- 2025/rust/day-05/src/main.rs | 59 ++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 22 deletions(-) diff --git a/2025/rust/day-05/src/main.rs b/2025/rust/day-05/src/main.rs index 46c51e1..763c0db 100644 --- a/2025/rust/day-05/src/main.rs +++ b/2025/rust/day-05/src/main.rs @@ -6,7 +6,7 @@ struct Range { } impl Range { - fn new(start: u64, end: u64) -> Range { + fn new(start: u64, end: u64) -> Self { Range { start, end } } @@ -14,7 +14,11 @@ impl Range { 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 { self.start = overlap.start; } @@ -22,16 +26,21 @@ impl Range { self.end = overlap.end; } } + + fn length(&self) -> u64 { + self.end - self.start + 1 + } } fn main() { 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!( - "How many of the available ingredient IDs are fresh? {}", - number_of_available_ids_in_rages(available_ids, ranges) + "Number of available IDs in 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, Vec) { @@ -50,23 +59,17 @@ fn parse_input(contents: &str) -> (Vec, Vec) { (ranges, available_ids) } -fn compress(mut ranges: Vec) -> Vec { +fn merge_overlapping_ranges(mut ranges: Vec) -> Vec { + ranges.sort_by_key(|range| range.start); + let mut compressed_ranges = vec![ranges.remove(0)]; for range in ranges { - let mut is_integrated = false; - for compressed_range in &mut compressed_ranges { - if compressed_range.contains(range.start) && compressed_range.contains(range.end) { - is_integrated = true; - break; - } - if compressed_range.contains(range.start) || compressed_range.contains(range.end) { - compressed_range.expand(&range); - is_integrated = true; - break; - } - } - if !is_integrated { + let previous = compressed_ranges.last_mut().unwrap(); + + if previous.overlaps(&range) { + previous.merge_with(&range); + } else { compressed_ranges.push(range); } } @@ -74,13 +77,17 @@ fn compress(mut ranges: Vec) -> Vec { compressed_ranges } -fn number_of_available_ids_in_rages(available_ids: Vec, ranges: Vec) -> usize { +fn count_available_ids_in_ranges(available_ids: Vec, ranges: &[Range]) -> usize { available_ids .iter() .filter(|id| ranges.iter().any(|range| range.contains(**id))) .count() } +fn count_ids_in_ranges(ranges: &[Range]) -> u64 { + ranges.iter().map(|range| range.length()).sum() +} + #[cfg(test)] mod tests { use super::*; @@ -102,8 +109,16 @@ mod tests { #[test] fn test_part1() { 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); } }