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
61    #[test]
62    fn test_normal_sequence() {
63        let pairs: Vec<_> = AdjacentPairs::from(vec![1, 2, 3, 4]).collect();
64        assert_eq!(pairs, vec![(1, 2), (2, 3), (3, 4)]);
65    }
66
67    #[test]
68    fn test_two_elements() {
69        let pairs: Vec<_> = AdjacentPairs::from(vec![10, 20]).collect();
70        assert_eq!(pairs, vec![(10, 20)]);
71    }
72
73    #[test]
74    fn test_single_element() {
75        let mut pairs = AdjacentPairs::from(vec![42]);
76        assert_eq!(pairs.next(), None);
77    }
78
79    #[test]
80    fn test_empty() {
81        let mut pairs = AdjacentPairs::from(Vec::<i32>::new());
82        assert_eq!(pairs.next(), None);
83    }
84
85    #[test]
86    fn test_duplicate_values() {
87        let pairs: Vec<_> = AdjacentPairs::from(vec![5, 5, 5]).collect();
88        assert_eq!(pairs, vec![(5, 5), (5, 5)]);
89    }
90
91    #[test]
92    fn test_step_by_step_iteration() {
93        let mut pairs = AdjacentPairs::from(vec![1, 2, 3]);
94        assert_eq!(pairs.next(), Some((1, 2)));
95        assert_eq!(pairs.next(), Some((2, 3)));
96        assert_eq!(pairs.next(), None);
97        // exhausted iterator stays exhausted
98        assert_eq!(pairs.next(), None);
99    }
100
101    #[test]
102    fn test_from_range() {
103        let pairs: Vec<_> = AdjacentPairs::from(0..5).collect();
104        assert_eq!(pairs, vec![(0, 1), (1, 2), (2, 3), (3, 4)]);
105    }
106}