use std::collections::VecDeque;
#[derive(Debug, Clone)]
pub struct Sorter<K: Ord + Default, V> {
outgoing: VecDeque<V>,
incoming: VecDeque<(K, V)>,
prev_max: K,
cur_max: K,
incoming_lte_prev_max_count: usize,
}
impl<K: Ord + Clone + Default, V> Default for Sorter<K, V> {
fn default() -> Self {
Self {
outgoing: VecDeque::new(),
incoming: VecDeque::new(),
prev_max: Default::default(),
cur_max: Default::default(),
incoming_lte_prev_max_count: 0,
}
}
}
impl<K: Ord + Clone + Default, V> Sorter<K, V> {
pub fn new() -> Self {
Default::default()
}
pub fn has_more(&self) -> bool {
!self.outgoing.is_empty()
}
pub fn get_next(&mut self) -> Option<V> {
self.outgoing.pop_front()
}
pub fn insert_unordered(&mut self, key: K, value: V) {
if key <= self.prev_max {
self.incoming_lte_prev_max_count += 1;
} else if key > self.cur_max {
self.cur_max = key.clone();
}
self.incoming.push_back((key, value));
}
pub fn finish_round(&mut self) {
if let Some(n) = self.incoming_lte_prev_max_count.checked_sub(1) {
let (new_outgoing, _middle, _remaining) = self
.incoming
.make_contiguous()
.select_nth_unstable_by_key(n, |(key, _value)| key.clone());
new_outgoing.sort_unstable_by_key(|(key, _value)| key.clone());
for _ in 0..self.incoming_lte_prev_max_count {
let (_key, value) = self.incoming.pop_front().unwrap();
self.outgoing.push_back(value);
}
}
self.prev_max = self.cur_max.clone();
self.incoming_lte_prev_max_count = self.incoming.len();
}
pub fn finish(&mut self) {
self.incoming
.make_contiguous()
.sort_unstable_by_key(|(key, _value)| key.clone());
while let Some((_key, value)) = self.incoming.pop_front() {
self.outgoing.push_back(value);
}
self.prev_max = self.cur_max.clone();
}
}
#[cfg(test)]
mod test {
use super::Sorter;
#[test]
fn it_works() {
let mut sorter = Sorter::new();
sorter.insert_unordered(1, "1"); sorter.insert_unordered(2, "2"); sorter.insert_unordered(3, "3"); sorter.insert_unordered(2, "2"); sorter.insert_unordered(4, "4"); assert_eq!(sorter.get_next(), None);
sorter.finish_round();
assert_eq!(sorter.get_next(), None);
sorter.insert_unordered(3, "3"); sorter.insert_unordered(5, "5"); sorter.insert_unordered(6, "6"); sorter.insert_unordered(7, "7"); sorter.insert_unordered(4, "4"); sorter.insert_unordered(5, "5"); assert_eq!(sorter.get_next(), None);
sorter.finish_round();
assert_eq!(sorter.get_next(), Some("1"));
assert_eq!(sorter.get_next(), Some("2"));
assert_eq!(sorter.get_next(), Some("2"));
assert_eq!(sorter.get_next(), Some("3"));
assert_eq!(sorter.get_next(), Some("3"));
assert_eq!(sorter.get_next(), Some("4"));
assert_eq!(sorter.get_next(), Some("4"));
assert_eq!(sorter.get_next(), None);
sorter.insert_unordered(6, "6"); sorter.insert_unordered(8, "8"); sorter.insert_unordered(9, "9"); sorter.insert_unordered(7, "7"); sorter.insert_unordered(10, "10"); assert_eq!(sorter.get_next(), None);
sorter.finish_round();
assert_eq!(sorter.get_next(), Some("5"));
assert_eq!(sorter.get_next(), Some("5"));
assert_eq!(sorter.get_next(), Some("6"));
assert_eq!(sorter.get_next(), Some("6"));
assert_eq!(sorter.get_next(), Some("7"));
assert_eq!(sorter.get_next(), Some("7"));
assert_eq!(sorter.get_next(), None);
sorter.finish();
assert_eq!(sorter.get_next(), Some("8"));
assert_eq!(sorter.get_next(), Some("9"));
assert_eq!(sorter.get_next(), Some("10"));
assert_eq!(sorter.get_next(), None);
}
}