Skip to content

Commit 2bd7305

Browse files
committed
refactor(05/2025): change implementation to Range and calculate intersection. It's faster, but fail for input"
1 parent ba45291 commit 2bd7305

File tree

2 files changed

+93
-7
lines changed

2 files changed

+93
-7
lines changed

src/solutions/year2025/day05.rs

Lines changed: 65 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use crate::solutions::Solution;
2+
use crate::utils::range::Range;
23
use itertools::Itertools;
4+
use std::collections::VecDeque;
35
use std::ops::RangeInclusive;
46

57
pub struct Day05;
@@ -15,14 +17,9 @@ impl Solution for Day05 {
1517
}
1618

1719
fn part_two(&self, input: &str) -> String {
18-
let (ranges, _) = self.parse(input);
20+
let ranges = self.parse_ranges(input);
1921

20-
ranges
21-
.iter()
22-
.flat_map(|range| range.clone())
23-
.unique()
24-
.count()
25-
.to_string()
22+
self.unique_ids(ranges.into_iter()).to_string()
2623
}
2724
}
2825

@@ -49,12 +46,59 @@ impl Day05 {
4946

5047
(ranges, ids)
5148
}
49+
50+
fn parse_ranges(&self, input: &str) -> Vec<Range> {
51+
let (ranges_str, _) = input.split_once("\n\n").unwrap();
52+
53+
ranges_str
54+
.lines()
55+
.map(|line| {
56+
let (start, end) = line.split_once("-").unwrap();
57+
58+
let start = start.parse::<isize>().unwrap();
59+
let end = end.parse::<isize>().unwrap();
60+
61+
Range::new(start, end).unwrap()
62+
})
63+
.collect_vec()
64+
}
65+
66+
fn unique_ids(&self, ranges: impl Iterator<Item = Range>) -> isize {
67+
let mut queue = VecDeque::from_iter(ranges);
68+
let mut result: Vec<Range> = Vec::new();
69+
70+
while let Some(range) = queue.pop_front() {
71+
result.push(range);
72+
// println!(" ==== {} ==== ", range);
73+
74+
for (k, other) in queue.clone().iter().enumerate() {
75+
if range.collide(other) {
76+
queue.remove(k);
77+
78+
let intersect = range.intersect(other).unwrap();
79+
let lefts = other.diff(&intersect);
80+
81+
// println!("{} collide: {} - {:?}", range, other, lefts);
82+
83+
for left in lefts {
84+
queue.push_back(left);
85+
}
86+
}
87+
}
88+
}
89+
90+
// println!("{:?}", result);
91+
92+
result.iter().map(|range| range.len()).sum::<isize>()
93+
}
5294
}
5395

5496
#[cfg(test)]
5597
mod tests {
5698
use crate::solutions::year2025::day05::Day05;
5799
use crate::solutions::Solution;
100+
use crate::utils::range::Range;
101+
use std::ops::RangeInclusive;
58102

59103
const EXAMPLE: &str = r#"3-5
60104
10-14
@@ -77,4 +121,18 @@ mod tests {
77121
fn part_two_example_test() {
78122
assert_eq!("14", Day05.part_two(EXAMPLE));
79123
}
124+
125+
#[test]
126+
fn unique_ids() {
127+
assert_eq!(8, run_unique_ids(vec![3..=5, 10..=14]));
128+
assert_eq!(5, run_unique_ids(vec![3..=5, 1..=4]));
129+
assert_eq!(6, run_unique_ids(vec![3..=7, 6..=8]));
130+
assert_eq!(7, run_unique_ids(vec![3..=7, 2..=8]));
131+
}
132+
133+
fn run_unique_ids(vec: Vec<RangeInclusive<isize>>) -> isize {
134+
let ranges = vec.into_iter().map(Range::from);
135+
136+
Day05.unique_ids(ranges)
137+
}
80138
}

src/utils/range.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use fmt::Display;
22
use std::fmt;
3+
use std::ops::RangeInclusive;
34

45
#[derive(Debug, Copy, Clone, PartialEq)]
56
pub struct Range {
@@ -113,6 +114,12 @@ impl Display for Range {
113114
}
114115
}
115116

117+
impl From<RangeInclusive<isize>> for Range {
118+
fn from(value: RangeInclusive<isize>) -> Self {
119+
Self::new(*value.start(), *value.end()).unwrap()
120+
}
121+
}
122+
116123
#[cfg(test)]
117124
mod tests {
118125
use crate::utils::range::Range;
@@ -174,4 +181,25 @@ mod tests {
174181
range.intersect(&Range::new(5, 7).unwrap())
175182
);
176183
}
184+
185+
#[test]
186+
fn diff() {
187+
let range = Range::new(3, 6).unwrap();
188+
189+
assert_eq!(
190+
vec![Range::new(3, 3).unwrap()],
191+
range.diff(&Range::new(4, 6).unwrap())
192+
);
193+
194+
assert_eq!(
195+
vec![Range::new(3, 3).unwrap(), Range::new(6, 6).unwrap(),],
196+
range.diff(&Range::new(4, 5).unwrap())
197+
);
198+
199+
// @fixme - why it doesnt work for that case?
200+
// assert_eq!(
201+
// Vec::<Range>::new(),
202+
// range.diff(&Range::new(10, 14).unwrap())
203+
// );
204+
}
177205
}

0 commit comments

Comments
 (0)