advent-of-code 2022.0.46

Solutions to Advent of Code
Documentation
pub struct TupleWindowIterator<I, T>
where
    I: Iterator<Item = T>,
    T: Copy,
{
    iterator: I,
    first_item: Option<T>,
}

impl<I, T> Iterator for TupleWindowIterator<I, T>
where
    I: Iterator<Item = T>,
    T: Copy,
{
    type Item = (T, T);

    fn next(&mut self) -> Option<Self::Item> {
        loop {
            match self.first_item {
                Some(item) => {
                    let next_element = self.iterator.next()?;
                    self.first_item = Some(next_element);
                    return Some((item, next_element));
                }
                None => {
                    self.first_item = Some(self.iterator.next()?);
                }
            }
        }
    }
}

impl<I, T> ExactSizeIterator for TupleWindowIterator<I, T>
where
    I: ExactSizeIterator<Item = T>,
    T: Copy,
{
    fn len(&self) -> usize {
        let result = usize::from(self.first_item.is_some()) + self.iterator.len();
        if result > 0 {
            result - 1
        } else {
            result
        }
    }
}

pub trait TupleWindowIteratorExt: Iterator {
    fn tuple_chunk(self) -> TupleWindowIterator<Self, Self::Item>
    where
        Self::Item: Copy,
        Self: Sized,
    {
        TupleWindowIterator {
            iterator: self,
            first_item: None,
        }
    }
}

impl<I: Iterator> TupleWindowIteratorExt for I {}

#[test]
fn test() {
    let a = [1, 2, 3, 4, 5, 6];
    let mut it = a.into_iter().tuple_chunk();
    assert_eq!(it.len(), 5);
    assert_eq!(it.next(), Some((1, 2)));
    assert_eq!(it.len(), 4);
    assert_eq!(it.next(), Some((2, 3)));
    assert_eq!(it.len(), 3);
    assert_eq!(it.next(), Some((3, 4)));
    assert_eq!(it.len(), 2);
    assert_eq!(it.next(), Some((4, 5)));
    assert_eq!(it.len(), 1);
    assert_eq!(it.next(), Some((5, 6)));
    assert_eq!(it.len(), 0);
    assert_eq!(it.next(), None);
    assert_eq!(it.len(), 0);
}