use std::cmp::Ordering;
use std::collections::BTreeSet;
use std::ops::Bound::{Excluded, Included, Unbounded};
#[derive(Copy, Clone)]
enum RangeEntry {
Start(u32),
End(u32),
}
impl RangeEntry {
fn index(&self) -> &u32 {
match self {
RangeEntry::Start(p) => p,
RangeEntry::End(p) => p,
}
}
}
impl PartialEq for RangeEntry {
fn eq(&self, other: &Self) -> bool {
self.index() == other.index()
}
}
impl Eq for RangeEntry {}
impl Ord for RangeEntry {
fn cmp(&self, other: &Self) -> Ordering {
self.index().cmp(other.index())
}
}
impl PartialOrd for RangeEntry {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.index().cmp(other.index()))
}
}
pub struct RangeSet {
entries: BTreeSet<RangeEntry>,
}
impl RangeSet {
pub fn new() -> Self {
RangeSet {
entries: BTreeSet::new(),
}
}
pub fn not_overlapping(&self, start: u32, end: u32) -> Vec<(u32, u32)> {
assert!(start < end);
let ranges = self.entries.range((
Included(RangeEntry::Start(start)),
Included(RangeEntry::End(end)),
));
let mut ret = Vec::<(u32, u32)>::new();
let mut current_start: Option<u32> = Some(start);
let mut num = 0;
for e in ranges {
num += 1;
match e {
RangeEntry::End(p) => {
if p < &end {
current_start = Some(*p);
}
}
RangeEntry::Start(p) => {
if current_start.unwrap() < *p {
ret.push((current_start.unwrap(), *p));
}
current_start = None;
}
}
}
if num == 0 {
let mut before = self
.entries
.range((Unbounded, Excluded(RangeEntry::Start(start))));
if let Some(RangeEntry::Start(_)) = before.next_back() {
return ret;
}
}
if let Some(s) = current_start {
if s < end {
assert!(s < end);
ret.push((s, end));
}
}
ret
}
pub fn add(&mut self, start: u32, end: u32) {
assert!(start < end);
let entries = self.entries.range((
Included(RangeEntry::Start(start)),
Included(RangeEntry::End(end)),
));
let mut to_remove = Vec::<RangeEntry>::new();
for e in entries {
to_remove.push(*e);
}
if to_remove.is_empty() {
let mut before = self
.entries
.range((Unbounded, Excluded(RangeEntry::Start(start))));
if let Some(RangeEntry::Start(_)) = before.next_back() {
return;
}
}
let first: Option<RangeEntry> = to_remove.first().copied();
let last: Option<RangeEntry> = to_remove.last().copied();
for e in to_remove {
self.entries.remove(&e);
}
match first {
Some(RangeEntry::Start(_)) | None => {
self.entries.insert(RangeEntry::Start(start));
}
_ => (),
}
match last {
Some(RangeEntry::End(_)) | None => {
self.entries.insert(RangeEntry::End(end));
}
_ => (),
}
}
}
#[test]
fn test_rangeset() {
let mut s = RangeSet::new();
assert_eq!(s.not_overlapping(0, u32::MAX), vec![(0, u32::MAX)]);
s.add(1, 5);
assert_eq!(s.not_overlapping(0, u32::MAX), vec![(0, 1), (5, u32::MAX)]);
assert_eq!(s.not_overlapping(2, u32::MAX), vec![(5, u32::MAX)]);
assert_eq!(s.not_overlapping(0, 3), vec![(0, 1)]);
assert_eq!(s.not_overlapping(5, u32::MAX), vec![(5, u32::MAX)]);
assert_eq!(s.not_overlapping(0, 1), vec![(0, 1)]);
assert_eq!(s.not_overlapping(1, 10), vec![(5, 10)]);
s.add(7, 10);
assert_eq!(
s.not_overlapping(0, u32::MAX),
vec![(0, 1), (5, 7), (10, u32::MAX)]
);
assert_eq!(s.not_overlapping(2, u32::MAX), vec![(5, 7), (10, u32::MAX)]);
assert_eq!(s.not_overlapping(0, 3), vec![(0, 1)]);
assert_eq!(s.not_overlapping(0, 1), vec![(0, 1)]);
assert_eq!(s.not_overlapping(6, u32::MAX), vec![(6, 7), (10, u32::MAX)]);
assert_eq!(s.not_overlapping(8, u32::MAX), vec![(10, u32::MAX)]);
assert_eq!(s.not_overlapping(6, 9), vec![(6, 7)]);
assert_eq!(s.not_overlapping(10, u32::MAX), vec![(10, u32::MAX)]);
assert_eq!(s.not_overlapping(7, 20), vec![(10, 20)]);
s.add(4, 7);
assert_eq!(s.not_overlapping(0, 1), vec![(0, 1)]);
assert_eq!(s.not_overlapping(0, u32::MAX), vec![(0, 1), (10, u32::MAX)]);
assert_eq!(s.not_overlapping(3, u32::MAX), vec![(10, u32::MAX)]);
assert_eq!(s.not_overlapping(0, 7), vec![(0, 1)]);
assert_eq!(s.not_overlapping(10, u32::MAX), vec![(10, u32::MAX)]);
assert_eq!(s.not_overlapping(1, 20), vec![(10, 20)]);
s.add(4, 7);
assert_eq!(s.not_overlapping(0, 1), vec![(0, 1)]);
assert_eq!(s.not_overlapping(0, u32::MAX), vec![(0, 1), (10, u32::MAX)]);
assert_eq!(s.not_overlapping(3, u32::MAX), vec![(10, u32::MAX)]);
assert_eq!(s.not_overlapping(0, 7), vec![(0, 1)]);
assert_eq!(s.not_overlapping(10, u32::MAX), vec![(10, u32::MAX)]);
assert_eq!(s.not_overlapping(1, 20), vec![(10, 20)]);
}