I'm getting myself acquainted with Rust and decided to implement the classical overlapping intervals problem.
Here is a statement of the problem:
Given a collection of intervals, write a function that merges all overlapping intervals and prints them out.
For example, given [1, 3], [2, 6], [8, 10], and [7, 11], the function should print [1, 6], [7, 11]. Or given [5, 12], and [8, 10] the function should print [5, 12].
You can assume that the first element of each interval is always less or equal than the second element of the interval.
This is my implementation:
use std::cmp;
use std::fmt::Write;
//--------------- Range ---------------//
#[derive(Copy, Clone)]
struct Range{
start: i32,
end: i32,
}
fn new_range(start: i32, end: i32)->Range{
Range{
start: start,
end: end,
}
}
impl Range{
fn overlaps(&self,other: &Range) -> bool{
(other.start >= self.start && other.start <= self.end)
|| (other.end >= self.start && other.end <= self.end)
}
fn merge(&mut self, other: &Range){
self.start = cmp::min(self.start, other.start);
self.end = cmp::max(self.end, other.end);
}
fn to_string(&self)->String{
format!("[{},{}]",self.start,self.end)
}
}
//--------------- RangeStack ----------------//
struct RangeStack{
ranges: Vec<Range>,
}
fn range_stack_with_ranges(ranges : &Vec<Range>)->RangeStack{
let mut raw_ranges = ranges.to_vec();
raw_ranges.sort_by(|a,b| a.start.cmp(&b.start));
let mut range_stack = RangeStack{
ranges: Vec::new(),
};
for range in raw_ranges.iter(){
range_stack.add(range);
}
range_stack
}
impl RangeStack{
//private
fn add(&mut self,range :&Range){
if self.ranges.len() == 0 {
self.ranges.push(range.clone());
}else if self.ranges.last_mut().unwrap().overlaps(range){
self.ranges.last_mut().unwrap().merge(range);
}else{
self.ranges.push(range.clone());
}
}
fn to_string(&self) -> String {
let mut res = String::new();
for range in self.ranges.iter() {
write!(&mut res, "{}", range.to_string()).unwrap();
}
res
}
}
//--------------- Main ---------------//
fn main() {
let v = vec![
new_range(3,6),
new_range(1,5),
new_range(7,11),
new_range(9,12),
new_range(4,8),
];
let rs = range_stack_with_ranges(&v);
print!("Result: {}\n",rs.to_string());
}
I would appreciate it if someone could review the Rust code and let me know if there is anything that is not idiomatic. In particular, I'm not sure if my usage of mut
would be considered ideal.