extern crate interval;
use self::interval::Collection;
use self::interval::Interval;
use self::interval::Set;
use std::fmt::Show;
use std::num::Int;
#[deriving(PartialEq, Show)]
pub struct IntegerSet<T: Int> {
intervals: Vec<Interval<T>>,
}
impl<T: Int> IntegerSet<T> {
pub fn new(intervals: Vec<Interval<T>>) -> IntegerSet<T> {
assert!(intervals.iter().all(|i| !i.is_empty()));
assert!(intervals.as_slice().windows(2).all(|is| {
assert_eq!(is.len(), 2);
let ref l = is[0];
let ref r = is[1];
l < r
}));
IntegerSet{intervals: intervals}
}
}
impl<T: Int> Collection for IntegerSet<T> {
fn is_empty(&self) -> bool { self.intervals.is_empty() }
fn len(&self) -> uint {
use std::iter::AdditiveIterator;
self.intervals.iter().map(|i| i.len()).sum()
}
}
impl<T: Int> Set<T> for IntegerSet<T> {
fn contains(&self, value: &T) -> bool {
self.intervals.iter().any(|interval| interval.contains(value))
}
fn is_disjoint(&self, _other: &IntegerSet<T>) -> bool {
panic!("not implemented")
}
fn is_subset(&self, _other: &IntegerSet<T>) -> bool {
panic!("not implemented")
}
}
fn touching<T: Int>(
mut a: Interval<T>, mut b: Interval<T>) -> bool {
if !a.is_disjoint(&b) { return true; }
if b < a { std::mem::swap(&mut a, &mut b); }
a.end + Int::one() == b.begin
}
fn merge<T: Int + Show>(a: Interval<T>, b: Interval<T>) -> Interval<T> {
assert!(touching(a, b));
let begin = std::cmp::min(a.begin, b.begin);
let end = std::cmp::max(a.end, b.end);
Interval::new(begin, end)
}
#[test]
fn test_merge() {
let a = Interval::new(1i, 2);
let b = Interval::new(2i, 3);
let merged = merge(a, b);
assert_eq!(merged, Interval::new(1, 3));
}
#[test]
fn test_merge_adjacent() {
let a = Interval::new(1i, 1);
let b = Interval::new(2i, 2);
let merged = merge(a, b);
assert_eq!(merged, Interval::new(1, 2));
}
impl<T: Int + Show> Add<Interval<T>, IntegerSet<T>> for Interval<T> {
fn add(self, rhs: Interval<T>) -> IntegerSet<T> {
if self.is_disjoint(&rhs) {
let intervals =
if self < rhs { vec![self, rhs] } else { vec![rhs, self] };
IntegerSet::new(intervals)
} else {
IntegerSet::new(vec![merge(self, rhs)])
}
}
}
impl<T: Int + Show> Sub<Interval<T>, IntegerSet<T>> for Interval<T> {
fn sub(self, rhs: Interval<T>) -> IntegerSet<T> {
if self.is_disjoint(&rhs) { return IntegerSet::new(vec![self]); }
if self.is_subset(&rhs) { return IntegerSet::new(Vec::new()); }
if rhs.is_subset(&self) {
let mut intervals = Vec::new();
let one = Int::one();
if self.begin + one < rhs.begin {
intervals.push(Interval::new(self.begin, rhs.begin - one));
}
if rhs.end < self.end - one {
intervals.push(Interval::new(rhs.end + one, self.end));
}
assert!(intervals.len() == 1 || intervals.len() == 2);
return IntegerSet::new(intervals);
}
let interval = if rhs < self {
Interval::new(rhs.end, self.end)
} else {
assert!(self < rhs);
Interval::new(self.begin, rhs.begin)
};
IntegerSet::new(vec![interval])
}
}
impl<T: Int + Show> Add<IntegerSet<T>, IntegerSet<T>> for IntegerSet<T> {
fn add(self, rhs: IntegerSet<T>) -> IntegerSet<T> {
let mut intervals = Vec::new();
let mut ls = self.intervals.iter().peekable();
let mut rs = rhs.intervals.iter().peekable();
while !ls.is_empty() && !rs.is_empty() {
let l = *ls.peek().unwrap();
let r = *rs.peek().unwrap();
let curr = if l.is_disjoint(r) {
let smaller = if l < r { &mut ls } else { &mut rs };
*smaller.next().unwrap()
} else {
merge(*ls.next().unwrap(), *rs.next().unwrap())
};
append(&mut intervals, curr);
}
for range in ls.chain(rs) {
append(&mut intervals, *range);
}
IntegerSet::new(intervals)
}
}
impl<T: Int + Show> Add<T, IntegerSet<T>> for IntegerSet<T> {
fn add(self, rhs: T) -> IntegerSet<T> {
let set = IntegerSet::new(vec![Interval::new(rhs, rhs)]);
self + set
}
}
fn append<T: Int + Show>(intervals: &mut Vec<Interval<T>>,
interval: Interval<T>) {
match intervals.pop() {
Some(last) => {
if last.is_disjoint(&interval) {
intervals.push(last);
intervals.push(interval);
} else {
intervals.push(merge(last, interval));
}
},
None => intervals.push(interval),
}
}
#[test]
fn test_empty() {
let empty: Interval<int> = Interval::empty();
assert!(empty.is_empty());
assert_eq!(empty.len(), 0);
assert!(!empty.contains(&0));
assert!(!empty.contains(&1));
}
#[test]
fn test_singleton() {
let i = Interval::new(1i, 1);
assert!(!i.is_empty());
assert_eq!(i.len(), 1);
assert!(!i.contains(&0));
assert!(i.contains(&1));
assert!(!i.contains(&2));
}