use std::rc::Rc;
use std::collections::HashMap;
use std::cmp::Ordering;
use std::hash::Hash;
use iterators::merge::Merge as Whatever;
use iterators::coalesce::Coalesce;
pub type W = i32;
#[derive(Debug, Eq, PartialEq)]
pub struct Trie<K, T, V> {
pub keys: Vec<(K, usize)>,
pub idxs: Vec<(usize, usize)>,
pub vals: Vec<(V, W)>,
pub times: Vec<(T, usize)>,
}
impl<K: Ord, T: Eq, V: Ord+Clone> Trie<K, T, V> {
pub fn new() -> Trie<K, T, V> {
Trie::with_capacities(0, 0, 0)
}
pub fn with_capacities(k: usize, i: usize, v: usize) -> Trie<K, T, V> {
Trie {
keys: Vec::with_capacity(k),
idxs: Vec::with_capacity(i),
vals: Vec::with_capacity(v),
times: Vec::new(),
}
}
pub fn len(&self) -> usize {
self.vals.len()
}
fn merge_and_push(&mut self, idxs: &mut [(usize, &[(V,W)])]) {
let vals_len = self.vals.len();
if idxs.len() == 1 {
self.vals.extend_from_slice(idxs[0].1);
}
else {
self.vals.extend(idxs.iter()
.map(|&(_, ref slice)| slice.iter().cloned())
.merge()
.coalesce());
}
if self.vals.len() > vals_len {
self.idxs.push((idxs[0].0, self.vals.len()));
self.times[idxs[0].0].1 += 1;
}
}
}
struct MergePart<K, T, V> {
trie: Rc<Trie<K, T, V>>,
remap: Vec<usize>,
key: usize,
}
impl<K, T, V> MergePart<K, T, V> {
fn new(trie: &Rc<Trie<K, T, V>>) -> MergePart<K, T, V> {
MergePart {
trie: trie.clone(),
remap: Vec::with_capacity(trie.times.len()),
key: 0,
}
}
fn key(&self) -> Option<&K> {
if self.key < self.trie.keys.len() {
Some(&self.trie.keys[self.key].0)
}
else {
None
}
}
}
pub struct Merge<K, T, V> {
part1: MergePart<K, T, V>,
part2: MergePart<K, T, V>,
result: Trie<K, T, V>,
}
impl<K: Ord+Clone, T: Eq+Clone+Hash, V: Ord+Clone> Merge<K, T, V> {
pub fn new<F: Fn(&T)->T>(trie1: &Rc<Trie<K, T, V>>, trie2: &Rc<Trie<K, T, V>>, advance: &F) -> Merge<K, T, V> {
let part1 = MergePart::<K, T, V>::new(trie1);
let part2 = MergePart::<K, T, V>::new(trie2);
let mut result = Merge { part1: part1, part2: part2, result: Trie::<K, T, V>::new() };
let mut times_map = HashMap::new();
for &(ref time, count) in trie1.times.iter() {
if count > 0 {
let time = advance(time);
if !times_map.contains_key(&time) {
let len = times_map.len();
times_map.insert(time.clone(), len);
result.result.times.push((time.clone(), 0));
}
result.part1.remap.push(times_map[&time]);
}
}
for &(ref time, count) in trie2.times.iter() {
if count > 0 {
let time = advance(time);
if !times_map.contains_key(&time) {
let len = times_map.len();
times_map.insert(time.clone(), len);
result.result.times.push((time.clone(), 0));
}
result.part2.remap.push(times_map[&time]);
}
}
result
}
pub fn step(&mut self) -> Option<Trie<K, T, V>> {
let (min1, min2) = {
let (min_key, min1, min2) = match (self.part1.key(), self.part2.key()) {
(None, None) => { return Some(::std::mem::replace(&mut self.result, Trie::new())); },
(Some(key), None) => (key, true, false),
(None, Some(key)) => (key, false, true),
(Some(key1), Some(key2)) => {
match key1.cmp(key2) {
Ordering::Less => (key1, true, false),
Ordering::Equal => (key1, true, true),
Ordering::Greater => (key2, false, true),
}
},
};
let mut to_merge = Vec::new();
if min1 {
let lower = if self.part1.key > 0 { self.part1.trie.keys[self.part1.key-1].1 } else { 0 };
for i in lower .. self.part1.trie.keys[self.part1.key].1 {
let (idx, off) = self.part1.trie.idxs[i];
let lower = if i > 0 { self.part1.trie.idxs[i-1].1 } else { 0 };
to_merge.push((self.part1.remap[idx], &self.part1.trie.vals[lower .. off]));
}
}
if min2 {
let lower = if self.part2.key > 0 { self.part2.trie.keys[self.part2.key-1].1 } else { 0 };
for i in lower .. self.part2.trie.keys[self.part2.key].1 {
let (idx, off) = self.part2.trie.idxs[i];
let lower = if i > 0 { self.part2.trie.idxs[i-1].1 } else { 0 };
to_merge.push((self.part2.remap[idx], &self.part2.trie.vals[lower .. off]));
}
}
to_merge.sort_by(|x,y| (x.0).cmp(&(y.0)));
let idxs_len = self.result.idxs.len();
let mut old_idx = 0;
let mut idx_cnt = 0;
for i in 0..to_merge.len() {
if i > 0 && old_idx != to_merge[i].0 {
self.result.merge_and_push(&mut to_merge[i - idx_cnt .. i]);
old_idx = to_merge[i].0;
idx_cnt = 0;
}
idx_cnt += 1;
}
let len = to_merge.len();
self.result.merge_and_push(&mut to_merge[len - idx_cnt .. len]);
if self.result.idxs.len() > idxs_len {
self.result.keys.push((min_key.clone(), self.result.idxs.len()));
}
(min1, min2)
};
if min1 { self.part1.key += 1; }
if min2 { self.part2.key += 1; }
None
}
}
#[cfg(test)]
mod tests {
use std::rc::Rc;
use super::{Trie, Merge};
#[test] fn merge_none() {
let trie1: Rc<Trie<u64, u64, u64>> = Rc::new(Trie::new());
let trie2: Rc<Trie<u64, u64, u64>> = Rc::new(Trie::new());
let mut merge = Merge::new(&trie1, &trie2, &|_x| 0);
loop {
println!("step");
if let Some(result) = merge.step() {
println!("yay");
println!("{:?}", result);
assert_eq!(result, Trie::new());
break;
}
}
}
#[test] fn merge_one() {
let trie1 = Rc::new(Trie {
keys: vec![("a", 2), ("b", 5), ("c", 6)],
idxs: vec![(0, 2), (1, 3), (0, 5), (1, 6), (2, 7), (0, 9)],
vals: vec![(0, 1), (1, 1), (0, -1), (0,1), (1,1), (1,-1), (0,-1), (2, 1), (3, 1)],
times: vec![(0, 3), (1, 2), (2, 1)],
});
let trie2 = Rc::new(Trie::new());
let mut merge = Merge::new(&trie1, &trie2, &|_x| 0);
loop {
println!("step");
if let Some(result) = merge.step() {
println!("yay");
println!("{:?}", result);
assert_eq!(result, Trie {
keys: vec![("a", 1), ("c", 2)],
idxs: vec![(0, 1), (0, 3)],
vals: vec![(1, 1), (2, 1), (3, 1)],
times: vec![(0, 2)],
});
break;
}
}
}
}