use std::iter::{FusedIterator};
pub fn map_filter_max<I: IntoIterator, T: Ord> (
it: I,
mut f: impl FnMut(I::Item) -> Option<T>,
) -> Option<usize> {
let mut it = it.into_iter().enumerate();
while let Some((i, x)) = it.next() {
if let Some(fx) = f(x) {
let mut best = (i, fx);
for (j, y) in it {
if let Some(fy) = f(y) {
if fy > best.1 {
best = (j, fy);
}
}
}
return Some(best.0);
}
}
None
}
pub trait AdHocFn<Input> {
type Output;
fn call(&self, input: Input) -> Self::Output;
}
impl<'a, T, U, F: AdHocFn<(&'a T, &'a U)>> AdHocFn<&'a (T, U)> for F {
type Output = F::Output;
fn call(&self, input: &'a (T, U)) -> Self::Output {
self.call((&input.0, &input.1))
}
}
impl<'a, T, U, F: AdHocFn<(&'a mut T, &'a mut U)>> AdHocFn<&'a mut (T, U)> for F {
type Output = F::Output;
fn call(&self, input: &'a mut (T, U)) -> Self::Output {
self.call((&mut input.0, &mut input.1))
}
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct First;
impl<T, U> AdHocFn<(T, U)> for First {
type Output = T;
fn call(&self, input: (T, U)) -> T { input.0 }
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Second;
impl<T, U> AdHocFn<(T, U)> for Second {
type Output = U;
fn call(&self, input: (T, U)) -> U { input.1 }
}
pub struct Map<I: Iterator, F: AdHocFn<I::Item>>(pub I, pub F);
impl<I: Iterator, F: AdHocFn<I::Item>> Iterator for Map<I, F> {
type Item = F::Output;
fn next(&mut self) -> Option<Self::Item> {
self.0.next().map(|x| self.1.call(x))
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
impl<I: DoubleEndedIterator, F: AdHocFn<I::Item>> DoubleEndedIterator for Map<I, F> {
fn next_back(&mut self) -> Option<Self::Item> {
self.0.next_back().map(|x| self.1.call(x))
}
}
impl<I: ExactSizeIterator, F: AdHocFn<I::Item>> ExactSizeIterator for Map<I, F> {}
impl<I: FusedIterator, F: AdHocFn<I::Item>> FusedIterator for Map<I, F> {}