use core::iter::{Cycle, Peekable, Skip, Take};
use core::ops::{AddAssign, Sub};
use itertools::{Intersperse, Itertools};
use num::Num;
use std::time::Instant;
impl<T: Iterator + Itertools + Sized> IterJaap for T {}
pub trait IterJaap: Iterator + Itertools {
fn rotate_left(self, n: usize) -> Rotate<Self>
where
Self: Clone + ExactSizeIterator,
{
let length = self.len();
let n = n % length;
self.cycle().skip(n).take(length)
}
fn rotate_right(self, n: usize) -> Rotate<Self>
where
Self: Clone + ExactSizeIterator,
{
let length = self.len();
let n = n % length; self.cycle().skip(length - n).take(length)
}
fn cumsum(self) -> CumSum<Self>
where
Self: Sized,
Self::Item: Default + AddAssign<Self::Item> + Copy,
{
CumSum {
iter: self,
acc: Self::Item::default(),
}
}
fn backpeekable(self) -> BackPeekable<Self>
where
Self: Sized,
{
BackPeekable {
iter: self,
previous: None,
}
}
fn intersperse_runs(self, size: usize, value: <Self as Iterator>::Item) -> IntersperseRuns<Self>
where
Self: Sized,
<Self as Iterator>::Item: Clone,
{
IntersperseRuns {
iter: self,
size,
index: 0,
value,
done_this: true,
}
}
fn outersperse(self, value: <Self as Iterator>::Item) -> Outersperse<Self>
where
Self: Sized,
<Self as Iterator>::Item: Clone,
{
#[allow(unstable_name_collisions)]
self.intersperse(value.clone()).surround(value)
}
fn surround(self, value: <Self as Iterator>::Item) -> Surround<Self>
where
Self: Sized,
<Self as Iterator>::Item: Clone,
{
self.prepend(value.clone()).append(value)
}
fn prepend(self, value: <Self as Iterator>::Item) -> Prepend<Self>
where
Self: Sized,
{
[value].into_iter().chain(self)
}
fn append(self, value: <Self as Iterator>::Item) -> Append<Self>
where
Self: Sized,
{
self.chain([value].into_iter())
}
fn timer() -> TimeIter {
TimeIter
}
fn pairs(self) -> Pairs<Self>
where
Self: Sized,
{
Pairs { iter: self }
}
fn recursive_iterator<T, F>(init: T, f: F) -> RecursiveIterator<T, F>
where
T: Clone,
F: Fn(&T) -> T,
{
RecursiveIterator {
state: init,
callback: f,
}
}
fn intersect<I>(self, iter2: I) -> Intersection<Self, I>
where
I: Iterator,
Self: Sized,
{
Intersection { iter1: self, iter2 }
}
fn collapse_consecutives(self) -> CollapseConsecutives<Self>
where
Self: Sized,
{
CollapseConsecutives {
iter: self.peekable(),
}
}
fn difference(self) -> Difference<Self>
where
Self: Sized,
Self::Item: Copy + Sub,
{
Difference {
iter: self.backpeekable(),
}
}
}
pub type Rotate<T> = Take<Skip<Cycle<T>>>;
pub type Append<T> = std::iter::Chain<T, std::array::IntoIter<<T as Iterator>::Item, 1>>;
pub type Prepend<T> = std::iter::Chain<std::array::IntoIter<<T as Iterator>::Item, 1>, T>;
pub type Surround<T> = Append<Prepend<T>>;
pub type Outersperse<T> = Surround<Intersperse<T>>;
pub struct TimeIter;
impl Iterator for TimeIter {
type Item = Instant;
fn next(&mut self) -> Option<Self::Item> {
Some(Instant::now())
}
}
pub struct IntersperseRuns<I>
where
I: Iterator,
<I as Iterator>::Item: Clone,
{
iter: I,
size: usize,
index: usize,
value: <I as Iterator>::Item,
done_this: bool,
}
impl<I> Iterator for IntersperseRuns<I>
where
I: Iterator,
<I as Iterator>::Item: Clone,
{
type Item = <I as Iterator>::Item;
fn next(&mut self) -> Option<Self::Item> {
if self.index % self.size == 0 && !self.done_this {
self.done_this = true;
Some(self.value.clone())
} else {
self.done_this = false;
self.index += 1;
self.iter.next()
}
}
}
pub struct BackPeekable<I>
where
I: Iterator,
{
iter: I,
previous: Option<<I as Iterator>::Item>,
}
impl<I> Iterator for BackPeekable<I>
where
I: Iterator,
<I as Iterator>::Item: Copy,
{
type Item = <I as Iterator>::Item;
fn next(&mut self) -> Option<Self::Item> {
self.previous = self.iter.next();
self.previous
}
}
impl<I> BackPeekable<I>
where
I: Iterator,
<I as Iterator>::Item: Copy,
{
pub fn peek_back(&self) -> Option<<Self as Iterator>::Item> {
self.previous
}
}
#[derive(Debug)]
pub struct CumSum<I>
where
I: Iterator,
I::Item: Default + AddAssign<I::Item> + Copy,
{
iter: I,
acc: I::Item,
}
impl<I> Iterator for CumSum<I>
where
I: Iterator,
I::Item: Default + AddAssign<I::Item> + Copy,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
self.acc += self.iter.next()?;
Some(self.acc)
}
}
#[derive(Debug)]
pub struct Pairs<I: Iterator> {
iter: I,
}
impl<I> Iterator for Pairs<I>
where
I: Iterator,
{
type Item = (I::Item, I::Item);
fn next(&mut self) -> Option<Self::Item> {
let first = self.iter.next()?;
let second = self.iter.next()?;
Some((first, second))
}
}
#[derive(Debug)]
pub struct RecursiveIterator<T, F>
where
F: Fn(&T) -> T,
T: Clone,
{
state: T,
callback: F,
}
impl<T, F> Iterator for RecursiveIterator<T, F>
where
F: Fn(&T) -> T,
T: Clone,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
let next_state = (self.callback)(&self.state);
self.state = next_state.clone();
Some(next_state)
}
}
pub struct CollapseConsecutives<I>
where
I: Iterator,
{
iter: Peekable<I>,
}
impl<I> Iterator for CollapseConsecutives<I>
where
I: Iterator<Item = usize>,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
let next_value = self.iter.next()?;
match self.iter.peek() {
Some(&value) if value == next_value + 1 => self.next(),
_ => Some(next_value),
}
}
}
pub struct Intersection<I, J>
where
I: Iterator,
J: Iterator,
{
iter1: I,
iter2: J,
}
impl<I, J> Intersection<I, J>
where
I: Iterator,
J: Iterator,
I::Item: Eq,
J::Item: Eq,
{
pub fn new(iter1: I, iter2: J) -> Self {
Self { iter1, iter2 }
}
}
impl<I, J, T> Iterator for Intersection<I, J>
where
I: Iterator<Item = T>,
J: Iterator<Item = T>,
T: Ord,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
let mut v1 = self.iter1.next()?;
let mut v2 = self.iter2.next()?;
loop {
if v1 < v2 {
v1 = self.iter1.next()?;
} else if v1 > v2 {
v2 = self.iter2.next()?;
} else {
break Some(v1);
}
}
}
}
pub struct Difference<I>
where
I: Iterator,
I::Item: Sub + Copy,
{
iter: BackPeekable<I>,
}
impl<I> Iterator for Difference<I>
where
I: Iterator,
I::Item: Sub<Output = I::Item> + Copy + Default,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
let last = self.iter.peek_back().unwrap_or(Default::default());
self.iter.next().map(|next| next - last)
}
}
pub trait SumResult<T: Num, E>: Iterator<Item = Result<T, E>> {
fn sum_result(self) -> Result<T, E>
where
Self: Sized,
{
let mut acc = T::zero();
for item in self {
acc = acc + item?;
}
Ok(acc)
}
}
impl<T: Num, E, I: Iterator<Item = Result<T, E>>> SumResult<T, E> for I {}