Skip to content

Instantly share code, notes, and snippets.

@raine
Created October 18, 2022 10:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save raine/151264e21f3438bf1f68302597d1a630 to your computer and use it in GitHub Desktop.
Save raine/151264e21f3438bf1f68302597d1a630 to your computer and use it in GitHub Desktop.
use itertools::Itertools;
use std::fmt;
#[derive(Debug)]
struct Range {
start: i32,
end: i32,
}
impl Range {
fn new(start: i32, end: i32) -> Self {
Range { start, end }
}
fn steps(&self) -> i32 {
self.end - self.start
}
}
impl fmt::Display for Range {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.start == self.end {
write!(f, "{}", self.start)
} else {
write!(f, "{}-{}", self.start, self.end)
}
}
}
pub fn range_extraction(ints: &[i32]) -> String {
// Construct Ranges for ints so that consecutive numbers belong to the same Range
let ranges: Vec<Range> = ints
.iter()
.fold(Vec::new(), |mut acc, n| match acc.last_mut() {
Some(mut prev) if prev.end + 1 == *n => {
prev.end = *n;
acc
}
Some(_) | None => {
acc.push(Range::new(*n, *n));
acc
}
});
ranges
.into_iter()
// For ranges that don't span 3 numbers, map them to Ranges that consist of a single number
.flat_map(|range| {
if range.steps() >= 2 {
vec![range]
} else {
(range.start..=range.end)
.map(|n| Range::new(n, n))
.collect()
}
})
.map(|range| format!("{}", range))
.join(",")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment