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}