Skip to main content

o1_utils/
adjacent_pairs.rs

1//! This module hosts the [`AdjacentPairs`] type.
2//!
3//! It can be used to list all the adjacent pairs of a list.
4//! For example, if you have a list of integers `[1, 2, 3]`,
5//! you can use it to obtain the list of tuples `[(1, 2), (2, 3)]`.
6
7/// You can create a new [`AdjacentPairs`] from an iterator using:
8///
9/// ```
10/// use o1_utils::adjacent_pairs::AdjacentPairs;
11///
12/// let a = vec![1, 2, 3];
13/// let mut pairs = AdjacentPairs::from(a);
14///
15/// assert_eq!(pairs.next(), Some((1, 2)));
16/// assert_eq!(pairs.next(), Some((2, 3)));
17/// assert_eq!(pairs.next(), None);
18/// ```
19pub struct AdjacentPairs<A, I>
20where
21    I: Iterator<Item = A>,
22{
23    prev_second_component: Option<A>,
24    i: I,
25}
26
27impl<A: Copy, I: Iterator<Item = A>> Iterator for AdjacentPairs<A, I> {
28    type Item = (A, A);
29
30    fn next(&mut self) -> Option<(A, A)> {
31        if let Some(x) = self.prev_second_component {
32            let y = self.i.next()?;
33            self.prev_second_component = Some(y);
34            Some((x, y))
35        } else {
36            let x = self.i.next()?;
37            let y = self.i.next()?;
38            self.prev_second_component = Some(y);
39            Some((x, y))
40        }
41    }
42}
43
44impl<A, I, T> From<T> for AdjacentPairs<A, I>
45where
46    T: IntoIterator<Item = A, IntoIter = I>,
47    I: Iterator<Item = A>,
48{
49    fn from(i: T) -> Self {
50        Self {
51            i: i.into_iter(),
52            prev_second_component: None,
53        }
54    }
55}
56
57#[cfg(test)]
58mod tests {
59    use super::*;
60    use alloc::{vec, vec::Vec};
61
62    #[test]
63    fn test_normal_sequence() {
64        let pairs: Vec<_> = AdjacentPairs::from(vec![1, 2, 3, 4]).collect();
65        assert_eq!(pairs, vec![(1, 2), (2, 3), (3, 4)]);
66    }
67
68    #[test]
69    fn test_two_elements() {
70        let pairs: Vec<_> = AdjacentPairs::from(vec![10, 20]).collect();
71        assert_eq!(pairs, vec![(10, 20)]);
72    }
73
74    #[test]
75    fn test_single_element() {
76        let mut pairs = AdjacentPairs::from(vec![42]);
77        assert_eq!(pairs.next(), None);
78    }
79
80    #[test]
81    fn test_empty() {
82        let mut pairs = AdjacentPairs::from(Vec::<i32>::new());
83        assert_eq!(pairs.next(), None);
84    }
85
86    #[test]
87    fn test_duplicate_values() {
88        let pairs: Vec<_> = AdjacentPairs::from(vec![5, 5, 5]).collect();
89        assert_eq!(pairs, vec![(5, 5), (5, 5)]);
90    }
91
92    #[test]
93    fn test_step_by_step_iteration() {
94        let mut pairs = AdjacentPairs::from(vec![1, 2, 3]);
95        assert_eq!(pairs.next(), Some((1, 2)));
96        assert_eq!(pairs.next(), Some((2, 3)));
97        assert_eq!(pairs.next(), None);
98        // exhausted iterator stays exhausted
99        assert_eq!(pairs.next(), None);
100    }
101
102    #[test]
103    fn test_from_range() {
104        let pairs: Vec<_> = AdjacentPairs::from(0..5).collect();
105        assert_eq!(pairs, vec![(0, 1), (1, 2), (2, 3), (3, 4)]);
106    }
107}