#![doc = include_str!("../README.md")]
use core::cmp::*;
use std::collections::BinaryHeap;
use ord_by::*;
pub struct NBest<T, F = ()>
where Self: NBestWrapper<T, F>
{
heap: BinaryHeap<<Self as NBestWrapper<T, F>>::InnerT>,
cmp_func: F,
}
#[doc(hidden)]
pub trait NBestWrapper<T, F> {
type InnerT: Ord;
fn _wrap_value_(&self, val: T) -> Self::InnerT;
fn _unwrap_value_(wrapped: Self::InnerT) -> T;
fn _unwrap_value_ref_<'a>(wrapped: &'a Self::InnerT) -> &'a T;
fn _cmp_func_() -> fn(&Self, &T, &T) -> Ordering;
}
impl<T: Ord> NBestWrapper<T, ()> for NBest<T, ()> {
type InnerT = Reverse<T>;
fn _wrap_value_(&self, val: T) -> Self::InnerT {
Reverse(val)
}
fn _unwrap_value_(wrapped: Self::InnerT) -> T {
wrapped.0
}
fn _unwrap_value_ref_<'a>(wrapped: &'a Self::InnerT) -> &'a T {
&wrapped.0
}
fn _cmp_func_() -> fn(&Self, &T, &T) -> Ordering {
fn reverse<T: Ord, S: NBestWrapper<T, ()>>(_n_best: &S, a: &T, b: &T) -> Ordering {
b.cmp(a)
}
reverse
}
}
impl<T, F: Fn(&T, &T) -> Ordering + Clone> NBestWrapper<T, F> for NBest<T, F> {
type InnerT = Reverse<OrdBy<T, F>>;
fn _wrap_value_(&self, val: T) -> Self::InnerT {
Reverse(OrdBy::new(val, self.cmp_func.clone()))
}
fn _unwrap_value_(wrapped: Self::InnerT) -> T {
wrapped.0.into_inner()
}
fn _unwrap_value_ref_<'a>(wrapped: &'a Self::InnerT) -> &'a T {
&wrapped.0.borrow()
}
fn _cmp_func_() -> fn(&Self, &T, &T) -> Ordering {
fn reverse<T, F>(n_best: &NBest<T, F>, a: &T, b: &T) -> Ordering
where
NBest<T, F>: NBestWrapper<T, F>,
F: Fn(&T, &T) -> Ordering
{
(n_best.cmp_func)(b, a)
}
reverse::<T, F>
}
}
impl<T: Ord> NBest<T, ()> {
pub fn new(n: usize) -> Self {
Self::new_internal(n, ())
}
pub fn with_iter<I>(n: usize, iter: I) -> Self
where I: IntoIterator<Item=T>
{
let mut new_collection = Self::new_internal(n, ());
for val in iter {
new_collection.push(val);
}
new_collection
}
}
impl<T, F: Fn(&T, &T) -> Ordering + Clone> NBest<T, F> {
pub fn with_cmp_fn(n: usize, func: F) -> Self
where F: Fn(&T, &T) -> Ordering,
{
Self::new_internal(n, func)
}
pub fn with_cmp_fn_and_iter<I>(n: usize, func: F, iter: I) -> Self
where
F: Fn(&T, &T) -> Ordering,
I: IntoIterator<Item=T>
{
let mut new_collection = Self::new_internal(n, func);
for val in iter {
new_collection.push(val);
}
new_collection
}
}
impl<T, F> NBest<T, F>
where Self: NBestWrapper<T, F>
{
fn new_internal(n: usize, func: F) -> Self {
if n < 1 {
panic!("0 capacity NBest is useless");
}
Self {
heap: BinaryHeap::with_capacity(n),
cmp_func: func,
}
}
pub fn push(&mut self, item: T) {
let value = self._wrap_value_(item);
if self.len() >= self.capacity() {
if self.heap.peek().unwrap() > &value { self.heap.pop();
self.heap.push(value);
}
} else {
self.heap.push(value);
}
}
pub fn pop(&mut self) -> Option<T> {
self.heap.pop().map(|val| Self::_unwrap_value_(val))
}
pub fn len(&self) -> usize {
self.heap.len()
}
pub fn capacity(&self) -> usize {
self.heap.capacity()
}
pub fn iter(&self) -> impl Iterator<Item=&T> {
self.heap.iter().map(|val| Self::_unwrap_value_ref_(val))
}
pub fn drain<'a>(&'a mut self) -> impl Iterator<Item=T> + 'a {
self.heap.drain().map(|val| Self::_unwrap_value_(val))
}
pub fn into_sorted_vec(mut self) -> Vec<T> {
let mut items: Vec<T> = self.drain().collect();
let cmp_func = Self::_cmp_func_();
items.sort_unstable_by(|a, b| cmp_func(&self, a, b));
items
}
}
#[doc(hidden)]
pub struct IntoIter<T, F> where NBest<T, F>: NBestWrapper<T, F> {
iter: core::iter::Map<std::collections::binary_heap::IntoIter<<NBest<T, F> as NBestWrapper<T, F>>::InnerT>, fn(val: <NBest<T, F> as NBestWrapper<T, F>>::InnerT) -> T >
}
impl<T, F> Iterator for IntoIter<T, F>
where NBest<T, F>: NBestWrapper<T, F>
{
type Item = T;
fn next(&mut self) -> Option<T> {
self.iter.next()
}
}
impl<T, F> IntoIterator for NBest<T, F>
where Self: NBestWrapper<T, F>
{
type Item = T;
type IntoIter = IntoIter<T, F>;
fn into_iter(self) -> Self::IntoIter {
IntoIter{
iter: self.heap.into_iter().map(|val| Self::_unwrap_value_(val))
}
}
}
impl<T, F> Extend<T> for NBest<T, F>
where Self: NBestWrapper<T, F>
{
fn extend<I: IntoIterator<Item=T>>(&mut self, iter: I) {
for val in iter {
self.push(val);
}
}
}
#[test]
fn test_cmp_fn() {
let numbers = vec![0, 2, 4, 6, 8, 1, 3, 5, 7, 9];
let mut n_best = NBest::with_cmp_fn_and_iter(4, |a, b| b.cmp(a), numbers);
n_best.push(1);
n_best.push(22);
assert_eq!(n_best.into_sorted_vec(), vec![0, 1, 1, 2]);
}
#[test]
fn test_ord() {
let numbers = vec![0, 2, 4, 6, 8, 1, 3, 5, 7, 9];
let mut n_best = NBest::new(4);
n_best.extend(numbers);
n_best.push(1);
n_best.push(22);
assert_eq!(n_best.into_sorted_vec(), vec![22, 9, 8, 7]);
}