use std::fmt::Show;
use std::num::Int;
#[deriving(Clone, Copy, PartialEq, Eq)]
pub struct Interval<T: Int> {
pub begin: T,
pub end: T,
}
impl<T: Int + Show> Interval<T> {
pub fn empty() -> Interval<T> {
let interval = Interval{begin: Int::one(), end: Int::zero()};
debug_assert!(interval.is_empty());
debug_assert_eq!(interval.len(), 0);
interval
}
pub fn new(begin: T, end: T) -> Interval<T> {
if begin > end { panic!("begin not <= end. [{}, {}]", begin, end); }
Interval{begin: begin, end: end}
}
}
impl<T: Int> PartialOrd for Interval<T> {
fn partial_cmp(&self, other: &Interval<T>) -> Option<Ordering> {
if self == other { return Some(Equal); }
if self.end < other.begin { return Some(Less); }
if self.begin > other.end { return Some(Greater); }
None
}
}
impl<T: Int + Show> Show for Interval<T> {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
if self.is_empty() {
write!(fmt, "∅")
} else {
write!(fmt, "[{}, {}]", self.begin, self.end)
}
}
}
pub trait Collection {
fn is_empty(&self) -> bool { self.len() == 0 }
fn len(&self) -> uint;
}
impl<T: Int> Collection for Interval<T> {
fn len(&self) -> uint {
let dist = self.end - self.begin + Int::one();
dist.to_uint().expect("could not determine length")
}
}
pub trait Set<T> {
fn contains(&self, value: &T) -> bool;
fn is_disjoint(&self, other: &Self) -> bool;
fn is_subset(&self, other: &Self) -> bool;
fn is_superset(&self, other: &Self) -> bool { other.is_subset(self) }
}
impl<T: Int> Set<T> for Interval<T> {
fn contains(&self, value: &T) -> bool {
*value >= self.begin && *value <= self.end
}
fn is_disjoint(&self, other: &Interval<T>) -> bool {
self.end < other.begin || self.begin > other.end
}
fn is_subset(&self, other: &Interval<T>) -> bool {
self.begin >= other.begin && self.end <= other.end
}
}
#[test]
fn test_show() {
let i = Interval::new(0i, 1);
assert_eq!(format!("{}", i), "[0, 1]".to_string());
}
#[test]
fn test_show_empty() {
let i: Interval<int> = Interval::empty();
assert_eq!(format!("{}", i), "∅".to_string());
}
#[test]
fn test_equality() {
let empty: Interval<int> = Interval::empty();
let i = Interval::new(0i, 1);
assert_eq!(empty, empty);
assert_eq!(i, i);
assert!(empty != i);
}
#[test]
fn test_ordering() {
let before = Interval::new(0i, 2);
let after = Interval::new(3i, 5);
assert!(before < after);
assert!(after > before);
let intersecting = Interval::new(1i, 4);
assert!(!(before < intersecting));
assert!(!(before > intersecting));
assert!(!(after < intersecting));
assert!(!(after > intersecting));
}
#[test]
#[ignore]
fn test_empty_ordering() {
let empty: Interval<int> = Interval::empty();
let i = Interval::new(-1, 0);
assert!(!(i < empty));
assert!(!(i > empty));
}
#[test]
fn test_empty_collection() {
let i: Interval<int> = Interval::empty();
assert!(i.is_empty());
assert_eq!(i.len(), 0);
}
#[test]
fn test_empty_set() {
let empty_set: Interval<int> = Interval::empty();
assert_eq!(empty_set.begin, Int::one());
assert_eq!(empty_set.end, Int::zero());
for i in [-1, 0, 1, 2].iter() { assert!(!empty_set.contains(i)); }
assert!(empty_set.is_disjoint(&empty_set));
assert!(empty_set.is_subset(&empty_set));
assert!(empty_set.is_superset(&empty_set));
}
#[test]
fn test_singleton() {
let singleton = Interval::new(1i, 1);
assert!(!singleton.is_empty());
assert_eq!(singleton.len(), 1);
assert!(singleton.contains(&1));
assert!(!singleton.contains(&0));
assert!(!singleton.contains(&2));
assert!(!singleton.is_disjoint(&singleton));
assert!(singleton.is_subset(&singleton));
assert!(singleton.is_superset(&singleton));
}
#[test]
fn test_abutting() {
let first = Interval::new(0i, 1);
let second = Interval::new(1i, 2);
assert!(!first.is_disjoint(&second));
assert!(!first.is_subset(&second));
assert!(!first.is_superset(&second));
}
#[test]
fn test_adjacent() {
let first = Interval::new(0i, 1);
let second = Interval::new(2i, 3);
assert!(first.is_disjoint(&second));
assert!(!first.is_subset(&second));
assert!(!first.is_superset(&second));
}