const_combinations/
lib.rs

1//! const fn combinations iter adapter
2//!
3//! # Examples
4//!
5//! ```
6//! use const_combinations::IterExt;
7//!
8//! let mut combinations = (1..5).combinations();
9//! assert_eq!(combinations.next(), Some([1, 2, 3]));
10//! assert_eq!(combinations.next(), Some([1, 2, 4]));
11//! assert_eq!(combinations.next(), Some([1, 3, 4]));
12//! assert_eq!(combinations.next(), Some([2, 3, 4]));
13//! assert_eq!(combinations.next(), None);
14//! ```
15
16#![no_std]
17
18extern crate alloc;
19
20mod combinations;
21mod permutations;
22
23pub use combinations::{Combinations, SliceCombinations};
24pub use permutations::{Permutations, SlicePermutations};
25
26/// An extension trait adding `combinations` and `permutations` to `Iterator`.
27pub trait IterExt: Iterator {
28    /// Return an iterator adaptor that iterates over the k-length combinations of
29    /// the elements from an iterator.
30    ///
31    /// The iterator produces a new array per iteration, and clones the iterator
32    /// elements. If `K` is greater than the length of the input iterator the
33    /// resulting iterator adaptor will yield no items.
34    ///
35    /// # Examples
36    ///
37    /// ```
38    /// use const_combinations::IterExt;
39    ///
40    /// let mut combinations = (1..5).combinations();
41    /// assert_eq!(combinations.next(), Some([1, 2, 3]));
42    /// assert_eq!(combinations.next(), Some([1, 2, 4]));
43    /// assert_eq!(combinations.next(), Some([1, 3, 4]));
44    /// assert_eq!(combinations.next(), Some([2, 3, 4]));
45    /// assert_eq!(combinations.next(), None);
46    /// ```
47    ///
48    /// Note: Combinations does not take into account the equality of the iterated values.
49    ///
50    /// ```
51    /// # use const_combinations::IterExt;
52    /// let mut combinations = vec![1, 2, 2].into_iter().combinations();
53    /// assert_eq!(combinations.next(), Some([1, 2])); // Note: these are the same
54    /// assert_eq!(combinations.next(), Some([1, 2])); // Note: these are the same
55    /// assert_eq!(combinations.next(), Some([2, 2]));
56    /// assert_eq!(combinations.next(), None);
57    /// ```
58    fn combinations<const K: usize>(self) -> Combinations<Self, K>
59    where
60        Self: Sized,
61        Self::Item: Clone,
62    {
63        Combinations::new(self)
64    }
65
66    /// Return an iterator adaptor that iterates over the k-length permutations of
67    /// the elements from an iterator.
68    ///
69    /// The iterator produces a new array per iteration, and clones the iterator
70    /// elements. If `K` is greater than the length of the input iterator the
71    /// resulting iterator adaptor will yield no items.
72    ///
73    /// # Examples
74    ///
75    /// ```
76    /// # use const_combinations::IterExt;
77    /// let mut permutations = (0..3).permutations();
78    /// assert_eq!(permutations.next(), Some([0, 1]));
79    /// assert_eq!(permutations.next(), Some([1, 0]));
80    /// assert_eq!(permutations.next(), Some([0, 2]));
81    /// assert_eq!(permutations.next(), Some([2, 0]));
82    /// assert_eq!(permutations.next(), Some([1, 2]));
83    /// assert_eq!(permutations.next(), Some([2, 1]));
84    /// assert_eq!(permutations.next(), None);
85    /// ```
86    ///
87    /// Note: Permutations does not take into account the equality of the iterated values.
88    ///
89    /// ```
90    /// # use const_combinations::IterExt;
91    /// let mut permutations = vec![2, 2].into_iter().permutations();
92    /// assert_eq!(permutations.next(), Some([2, 2])); // Note: these are the same
93    /// assert_eq!(permutations.next(), Some([2, 2])); // Note: these are the same
94    /// assert_eq!(permutations.next(), None);
95    /// ```
96    fn permutations<const K: usize>(self) -> Permutations<Self, K>
97    where
98        Self: Sized,
99        Self::Item: Clone,
100    {
101        Permutations::new(self)
102    }
103}
104
105impl<I> IterExt for I where I: Iterator {}
106
107/// An extension trait adding `combinations` and `permutations` to `Slice`.
108pub trait SliceExt<T> {
109    /// Return an iterator that iterates over the k-length combinations of
110    /// the elements from a slice.
111    ///
112    /// The iterator produces a new array per iteration, and returns references to the
113    /// elements of the slice. If `K` is greater than the length of the input slice the
114    /// resulting iterator will yield no items.
115    ///
116    /// # Examples
117    ///
118    /// ```
119    /// use const_combinations::SliceExt;
120    ///
121    /// let mut combinations = [1, 2, 3, 4].combinations();
122    /// assert_eq!(combinations.next(), Some([&1, &2, &3]));
123    /// assert_eq!(combinations.next(), Some([&1, &2, &4]));
124    /// assert_eq!(combinations.next(), Some([&1, &3, &4]));
125    /// assert_eq!(combinations.next(), Some([&2, &3, &4]));
126    /// assert_eq!(combinations.next(), None);
127    /// ```
128    ///
129    /// Note: Combinations does not take into account the equality of the slice elements.
130    ///
131    /// ```
132    /// # use const_combinations::SliceExt;
133    /// let mut combinations = [1, 2, 2].combinations();
134    /// assert_eq!(combinations.next(), Some([&1, &2])); // Note: these are the same
135    /// assert_eq!(combinations.next(), Some([&1, &2])); // Note: these are the same
136    /// assert_eq!(combinations.next(), Some([&2, &2]));
137    /// assert_eq!(combinations.next(), None);
138    /// ```
139    fn combinations<const K: usize>(&self) -> SliceCombinations<'_, T, K>;
140
141    /// Return an iterator that iterates over the k-length permutations of
142    /// the elements from a slice.
143    ///
144    /// The iterator produces a new array per iteration, and clones the iterator
145    /// elements. If `K` is greater than the length of the input slice the
146    /// resulting iterator adaptor will yield no items.
147    ///
148    /// # Examples
149    ///
150    /// ```
151    /// # use const_combinations::SliceExt;
152    /// let mut permutations = [0, 1, 2].permutations();
153    /// assert_eq!(permutations.next(), Some([&0, &1]));
154    /// assert_eq!(permutations.next(), Some([&1, &0]));
155    /// assert_eq!(permutations.next(), Some([&0, &2]));
156    /// assert_eq!(permutations.next(), Some([&2, &0]));
157    /// assert_eq!(permutations.next(), Some([&1, &2]));
158    /// assert_eq!(permutations.next(), Some([&2, &1]));
159    /// assert_eq!(permutations.next(), None);
160    /// ```
161    ///
162    /// Note: Permutations does not take into account the equality of the slice elements.
163    ///
164    /// ```
165    /// # use const_combinations::SliceExt;
166    /// let mut permutations = [2, 2].permutations();
167    /// assert_eq!(permutations.next(), Some([&2, &2])); // Note: these are the same
168    /// assert_eq!(permutations.next(), Some([&2, &2])); // Note: these are the same
169    /// assert_eq!(permutations.next(), None);
170    /// ```
171    fn permutations<const K: usize>(&self) -> SlicePermutations<'_, T, K>;
172}
173
174impl<T> SliceExt<T> for [T] {
175    fn combinations<const K: usize>(&self) -> SliceCombinations<'_, T, K> {
176        SliceCombinations::new(self)
177    }
178    fn permutations<const K: usize>(&self) -> SlicePermutations<'_, T, K> {
179        SlicePermutations::new(self)
180    }
181}