use std::slice;
use std::default::Default;
use std::fmt::{self, Debug};
use std::iter::{self, IntoIterator};
use compare::{Compare, Natural, natural};
fn is_root(x: usize) -> bool { x < 2 }
fn left(x: usize) -> usize { x & !1 }
fn parent_left(x: usize) -> usize {
debug_assert!(!is_root(x));
left((x - 2) / 2)
}
fn interval_heap_push<T, C: Compare<T>>(v: &mut [T], cmp: &C) {
debug_assert!(v.len() > 0);
let mut node_max = v.len() - 1;
let mut node_min = left(node_max);
if cmp.compares_gt(&v[node_min], &v[node_max]) { v.swap(node_min, node_max); }
while !is_root(node_min) {
let par_min = parent_left(node_min);
let par_max = par_min + 1;
if cmp.compares_lt(&v[node_min], &v[par_min]) {
v.swap(par_min, node_min);
} else if cmp.compares_lt(&v[par_max], &v[node_max]) {
v.swap(par_max, node_max);
} else {
return; }
debug_assert!(cmp.compares_le(&v[node_min], &v[node_max]));
node_min = par_min;
node_max = par_max;
}
}
fn update_min<T, C: Compare<T>>(v: &mut [T], cmp: &C) {
debug_assert!(cmp.compares_le(&v[0], &v[1]));
let mut left = 0;
loop {
let c1 = left * 2 + 2; let c2 = left * 2 + 4; if v.len() <= c1 { return; } let ch = if v.len() <= c2 || cmp.compares_lt(&v[c1], &v[c2]) { c1 }
else { c2 };
if cmp.compares_lt(&v[ch], &v[left]) {
v.swap(ch, left);
left = ch;
let right = left + 1;
if right < v.len() {
if cmp.compares_gt(&v[left], &v[right]) { v.swap(left, right); }
}
} else {
break;
}
}
}
fn update_max<T, C: Compare<T>>(v: &mut [T], cmp: &C) {
debug_assert!(cmp.compares_le(&v[0], &v[1]));
let mut right = 1;
loop {
let c1 = right * 2 + 1; let c2 = right * 2 + 3; if v.len() <= c1 { return; } let ch = if v.len() <= c2 || cmp.compares_gt(&v[c1], &v[c2]) { c1 }
else { c2 };
if cmp.compares_gt(&v[ch], &v[right]) {
v.swap(ch, right);
right = ch;
let left = right - 1; if cmp.compares_gt(&v[left], &v[right]) { v.swap(left, right); }
} else {
break;
}
}
}
#[derive(Clone)]
pub struct IntervalHeap<T, C: Compare<T> = Natural<T>> {
data: Vec<T>,
cmp: C,
}
impl<T, C: Compare<T> + Default> Default for IntervalHeap<T, C> {
#[inline]
fn default() -> IntervalHeap<T, C> {
IntervalHeap::with_comparator(Default::default())
}
}
pub struct Iter<'a, T: 'a>(slice::Iter<'a, T>);
impl<T: Ord> IntervalHeap<T> {
pub fn new() -> IntervalHeap<T> { IntervalHeap::with_comparator(natural()) }
pub fn with_capacity(capacity: usize) -> IntervalHeap<T> {
IntervalHeap::with_capacity_and_comparator(capacity, natural())
}
pub fn from_vec(vec: Vec<T>) -> IntervalHeap<T> {
IntervalHeap::from_vec_and_comparator(vec, natural())
}
}
impl<T, C: Compare<T>> IntervalHeap<T, C> {
pub fn with_comparator(cmp: C) -> IntervalHeap<T, C> {
IntervalHeap { data: vec![], cmp: cmp }
}
pub fn with_capacity_and_comparator(capacity: usize, cmp: C) -> IntervalHeap<T, C> {
IntervalHeap { data: Vec::with_capacity(capacity), cmp: cmp }
}
pub fn from_vec_and_comparator(mut vec: Vec<T>, cmp: C) -> IntervalHeap<T, C> {
for to in 2 .. vec.len() + 1 {
interval_heap_push(&mut vec[..to], &cmp);
}
let heap = IntervalHeap { data: vec, cmp: cmp };
debug_assert!(heap.is_valid());
heap
}
pub fn iter(&self) -> Iter<T> {
debug_assert!(self.is_valid());
Iter(self.data.iter())
}
pub fn get_min(&self) -> Option<&T> {
debug_assert!(self.is_valid());
match self.data.len() {
0 => None,
_ => Some(&self.data[0])
}
}
pub fn get_max(&self) -> Option<&T> {
debug_assert!(self.is_valid());
match self.data.len() {
0 => None,
1 => Some(&self.data[0]),
_ => Some(&self.data[1])
}
}
pub fn get_min_max(&self) -> Option<(&T, &T)> {
debug_assert!(self.is_valid());
match self.data.len() {
0 => None,
1 => Some((&self.data[0],&self.data[0])),
_ => Some((&self.data[0],&self.data[1]))
}
}
pub fn capacity(&self) -> usize {
self.data.capacity()
}
pub fn reserve_exact(&mut self, additional: usize) {
self.data.reserve_exact(additional);
}
pub fn reserve(&mut self, additional: usize) {
self.data.reserve(additional);
}
pub fn shrink_to_fit(&mut self) {
self.data.shrink_to_fit()
}
pub fn pop_min(&mut self) -> Option<T> {
debug_assert!(self.is_valid());
let min = match self.data.len() {
0 => None,
1...2 => Some(self.data.swap_remove(0)),
_ => {
let res = self.data.swap_remove(0);
update_min(self.data.as_mut_slice(), &self.cmp);
Some(res)
}
};
debug_assert!(self.is_valid());
min
}
pub fn pop_max(&mut self) -> Option<T> {
debug_assert!(self.is_valid());
let max = match self.data.len() {
0...2 => self.data.pop(),
_ => {
let res = self.data.swap_remove(1);
update_max(self.data.as_mut_slice(), &self.cmp);
Some(res)
}
};
debug_assert!(self.is_valid());
max
}
pub fn push(&mut self, x: T) {
debug_assert!(self.is_valid());
self.data.push(x);
interval_heap_push(self.data.as_mut_slice(), &self.cmp);
debug_assert!(self.is_valid());
}
pub fn into_vec(self) -> Vec<T> { self.data }
pub fn into_sorted_vec(self) -> Vec<T> {
let mut vec = self.data;
for hsize in range(2, vec.len()).rev() {
vec.swap(1, hsize);
update_max(&mut vec[..hsize], &self.cmp);
}
vec
}
pub fn len(&self) -> usize {
self.data.len()
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
pub fn clear(&mut self) {
self.data.clear();
}
fn is_valid(&self) -> bool {
let mut nodes = self.data.chunks(2);
match nodes.next() {
Some([ref l, ref r]) => self.cmp.compares_le(l, r) && nodes.enumerate().all(|(i, node)| {
let p = i & !1;
let l = &node[0];
let r = node.last().unwrap();
self.cmp.compares_le(l, r) && self.cmp.compares_ge(l, &self.data[p]) && self.cmp.compares_le(r, &self.data[p + 1]) }),
_ => true, }
}
}
impl<T: Debug, C: Compare<T>> Debug for IntervalHeap<T, C> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, "{{"));
let mut it = self.iter();
if let Some(item) = it.next() {
try!(write!(f, "{:?}", item));
for item in it { try!(write!(f, ", {:?}", item)); }
}
write!(f, "}}")
}
}
impl<T, C: Compare<T> + Default> iter::FromIterator<T> for IntervalHeap<T, C> {
fn from_iter<I: IntoIterator<Item=T>>(iter: I) -> IntervalHeap<T, C> {
IntervalHeap::from_vec_and_comparator(iter.into_iter().collect(), Default::default())
}
}
impl<T, C: Compare<T>> Extend<T> for IntervalHeap<T, C> {
fn extend<I: IntoIterator<Item=T>>(&mut self, iterable: I) {
let iter = iterable.into_iter();
let (lower, _) = iter.size_hint();
self.reserve(lower);
for elem in iter {
self.push(elem);
}
}
}
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
#[inline] fn next(&mut self) -> Option<&'a T> { self.0.next() }
#[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.0.size_hint() }
}
impl<'a, T, C: Compare<T>> IntoIterator for &'a IntervalHeap<T, C> {
type Item = &'a T;
type IntoIter = Iter<'a, T>;
fn into_iter(self) -> Iter<'a, T> { self.iter() }
}
#[cfg(test)]
mod test {
use rand::{thread_rng, Rng};
use super::IntervalHeap;
#[test]
fn fuzz_push_into_sorted_vec() {
let mut rng = thread_rng();
let mut tmp = Vec::with_capacity(100);
for _ in range(0, 100) {
tmp.clear();
let mut ih = IntervalHeap::from_vec(tmp);
for _ in range(0, 100) {
ih.push(rng.next_u32());
}
tmp = ih.into_sorted_vec();
for pair in tmp.windows(2) {
assert!(pair[0] <= pair[1]);
}
}
}
#[test]
fn fuzz_pop_min() {
let mut rng = thread_rng();
let mut tmp = Vec::with_capacity(100);
for _ in range(0, 100) {
tmp.clear();
let mut ih = IntervalHeap::from_vec(tmp);
for _ in range(0, 100) {
ih.push(rng.next_u32());
}
let mut tmpx: Option<u32> = None;
loop {
let tmpy = ih.pop_min();
match (tmpx, tmpy) {
(_, None) => break,
(Some(x), Some(y)) => assert!(x <= y),
_ => ()
}
tmpx = tmpy;
}
tmp = ih.into_vec();
}
}
#[test]
fn fuzz_pop_max() {
let mut rng = thread_rng();
let mut tmp = Vec::with_capacity(100);
for _ in range(0, 100) {
tmp.clear();
let mut ih = IntervalHeap::from_vec(tmp);
for _ in range(0, 100) {
ih.push(rng.next_u32());
}
let mut tmpx: Option<u32> = None;
loop {
let tmpy = ih.pop_max();
match (tmpx, tmpy) {
(_, None) => break,
(Some(x), Some(y)) => assert!(x >= y),
_ => ()
}
tmpx = tmpy;
}
tmp = ih.into_vec();
}
}
#[test]
fn test_from_vec() {
let heap = IntervalHeap::<i32>::from_vec(vec![]);
assert_eq!(heap.get_min_max(), None);
let heap = IntervalHeap::from_vec(vec![2]);
assert_eq!(heap.get_min_max(), Some((&2, &2)));
let heap = IntervalHeap::from_vec(vec![2, 1]);
assert_eq!(heap.get_min_max(), Some((&1, &2)));
let heap = IntervalHeap::from_vec(vec![2, 1, 3]);
assert_eq!(heap.get_min_max(), Some((&1, &3)));
}
#[test]
fn test_is_valid() {
fn new(data: Vec<i32>) -> IntervalHeap<i32> {
IntervalHeap { data: data, cmp: ::compare::natural() }
}
assert!(new(vec![]).is_valid());
assert!(new(vec![1]).is_valid());
assert!(new(vec![1, 1]).is_valid());
assert!(new(vec![1, 5]).is_valid());
assert!(new(vec![1, 5, 1]).is_valid());
assert!(new(vec![1, 5, 1, 1]).is_valid());
assert!(new(vec![1, 5, 5]).is_valid());
assert!(new(vec![1, 5, 5, 5]).is_valid());
assert!(new(vec![1, 5, 2, 4]).is_valid());
assert!(new(vec![1, 5, 2, 4, 3]).is_valid());
assert!(new(vec![1, 5, 2, 4, 3, 3]).is_valid());
assert!(!new(vec![2, 1]).is_valid()); assert!(!new(vec![1, 5, 4, 3]).is_valid()); assert!(!new(vec![1, 5, 0]).is_valid()); assert!(!new(vec![1, 5, 0, 5]).is_valid()); assert!(!new(vec![1, 5, 6]).is_valid()); assert!(!new(vec![1, 5, 1, 6]).is_valid()); assert!(!new(vec![1, 5, 0, 6]).is_valid()); }
}