/rust/registry/src/index.crates.io-1949cf8c6b5b557f/itertools-0.14.0/src/permutations.rs
Line | Count | Source |
1 | | use alloc::boxed::Box; |
2 | | use alloc::vec::Vec; |
3 | | use std::fmt; |
4 | | use std::iter::once; |
5 | | use std::iter::FusedIterator; |
6 | | |
7 | | use super::lazy_buffer::LazyBuffer; |
8 | | use crate::size_hint::{self, SizeHint}; |
9 | | |
10 | | /// An iterator adaptor that iterates through all the `k`-permutations of the |
11 | | /// elements from an iterator. |
12 | | /// |
13 | | /// See [`.permutations()`](crate::Itertools::permutations) for |
14 | | /// more information. |
15 | | #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] |
16 | | pub struct Permutations<I: Iterator> { |
17 | | vals: LazyBuffer<I>, |
18 | | state: PermutationState, |
19 | | } |
20 | | |
21 | | impl<I> Clone for Permutations<I> |
22 | | where |
23 | | I: Clone + Iterator, |
24 | | I::Item: Clone, |
25 | | { |
26 | | clone_fields!(vals, state); |
27 | | } |
28 | | |
29 | | #[derive(Clone, Debug)] |
30 | | enum PermutationState { |
31 | | /// No permutation generated yet. |
32 | | Start { k: usize }, |
33 | | /// Values from the iterator are not fully loaded yet so `n` is still unknown. |
34 | | Buffered { k: usize, min_n: usize }, |
35 | | /// All values from the iterator are known so `n` is known. |
36 | | Loaded { |
37 | | indices: Box<[usize]>, |
38 | | cycles: Box<[usize]>, |
39 | | }, |
40 | | /// No permutation left to generate. |
41 | | End, |
42 | | } |
43 | | |
44 | | impl<I> fmt::Debug for Permutations<I> |
45 | | where |
46 | | I: Iterator + fmt::Debug, |
47 | | I::Item: fmt::Debug, |
48 | | { |
49 | | debug_fmt_fields!(Permutations, vals, state); |
50 | | } |
51 | | |
52 | 0 | pub fn permutations<I: Iterator>(iter: I, k: usize) -> Permutations<I> { |
53 | 0 | Permutations { |
54 | 0 | vals: LazyBuffer::new(iter), |
55 | 0 | state: PermutationState::Start { k }, |
56 | 0 | } |
57 | 0 | } |
58 | | |
59 | | impl<I> Iterator for Permutations<I> |
60 | | where |
61 | | I: Iterator, |
62 | | I::Item: Clone, |
63 | | { |
64 | | type Item = Vec<I::Item>; |
65 | | |
66 | 0 | fn next(&mut self) -> Option<Self::Item> { |
67 | 0 | let Self { vals, state } = self; |
68 | 0 | match state { |
69 | | PermutationState::Start { k: 0 } => { |
70 | 0 | *state = PermutationState::End; |
71 | 0 | Some(Vec::new()) |
72 | | } |
73 | 0 | &mut PermutationState::Start { k } => { |
74 | 0 | vals.prefill(k); |
75 | 0 | if vals.len() != k { |
76 | 0 | *state = PermutationState::End; |
77 | 0 | return None; |
78 | 0 | } |
79 | 0 | *state = PermutationState::Buffered { k, min_n: k }; |
80 | 0 | Some(vals[0..k].to_vec()) |
81 | | } |
82 | 0 | PermutationState::Buffered { ref k, min_n } => { |
83 | 0 | if vals.get_next() { |
84 | 0 | let item = (0..*k - 1) |
85 | 0 | .chain(once(*min_n)) |
86 | 0 | .map(|i| vals[i].clone()) |
87 | 0 | .collect(); |
88 | 0 | *min_n += 1; |
89 | 0 | Some(item) |
90 | | } else { |
91 | 0 | let n = *min_n; |
92 | 0 | let prev_iteration_count = n - *k + 1; |
93 | 0 | let mut indices: Box<[_]> = (0..n).collect(); |
94 | 0 | let mut cycles: Box<[_]> = (n - k..n).rev().collect(); |
95 | | // Advance the state to the correct point. |
96 | 0 | for _ in 0..prev_iteration_count { |
97 | 0 | if advance(&mut indices, &mut cycles) { |
98 | 0 | *state = PermutationState::End; |
99 | 0 | return None; |
100 | 0 | } |
101 | | } |
102 | 0 | let item = vals.get_at(&indices[0..*k]); |
103 | 0 | *state = PermutationState::Loaded { indices, cycles }; |
104 | 0 | Some(item) |
105 | | } |
106 | | } |
107 | 0 | PermutationState::Loaded { indices, cycles } => { |
108 | 0 | if advance(indices, cycles) { |
109 | 0 | *state = PermutationState::End; |
110 | 0 | return None; |
111 | 0 | } |
112 | 0 | let k = cycles.len(); |
113 | 0 | Some(vals.get_at(&indices[0..k])) |
114 | | } |
115 | 0 | PermutationState::End => None, |
116 | | } |
117 | 0 | } |
118 | | |
119 | 0 | fn count(self) -> usize { |
120 | 0 | let Self { vals, state } = self; |
121 | 0 | let n = vals.count(); |
122 | 0 | state.size_hint_for(n).1.unwrap() |
123 | 0 | } |
124 | | |
125 | 0 | fn size_hint(&self) -> SizeHint { |
126 | 0 | let (mut low, mut upp) = self.vals.size_hint(); |
127 | 0 | low = self.state.size_hint_for(low).0; |
128 | 0 | upp = upp.and_then(|n| self.state.size_hint_for(n).1); |
129 | 0 | (low, upp) |
130 | 0 | } |
131 | | } |
132 | | |
133 | | impl<I> FusedIterator for Permutations<I> |
134 | | where |
135 | | I: Iterator, |
136 | | I::Item: Clone, |
137 | | { |
138 | | } |
139 | | |
140 | 0 | fn advance(indices: &mut [usize], cycles: &mut [usize]) -> bool { |
141 | 0 | let n = indices.len(); |
142 | 0 | let k = cycles.len(); |
143 | | // NOTE: if `cycles` are only zeros, then we reached the last permutation. |
144 | 0 | for i in (0..k).rev() { |
145 | 0 | if cycles[i] == 0 { |
146 | 0 | cycles[i] = n - i - 1; |
147 | 0 | indices[i..].rotate_left(1); |
148 | 0 | } else { |
149 | 0 | let swap_index = n - cycles[i]; |
150 | 0 | indices.swap(i, swap_index); |
151 | 0 | cycles[i] -= 1; |
152 | 0 | return false; |
153 | | } |
154 | | } |
155 | 0 | true |
156 | 0 | } |
157 | | |
158 | | impl PermutationState { |
159 | 0 | fn size_hint_for(&self, n: usize) -> SizeHint { |
160 | | // At the beginning, there are `n!/(n-k)!` items to come. |
161 | 0 | let at_start = |n, k| { |
162 | 0 | debug_assert!(n >= k); |
163 | 0 | let total = (n - k + 1..=n).try_fold(1usize, |acc, i| acc.checked_mul(i)); |
164 | 0 | (total.unwrap_or(usize::MAX), total) |
165 | 0 | }; |
166 | 0 | match *self { |
167 | 0 | Self::Start { k } if n < k => (0, Some(0)), |
168 | 0 | Self::Start { k } => at_start(n, k), |
169 | 0 | Self::Buffered { k, min_n } => { |
170 | | // Same as `Start` minus the previously generated items. |
171 | 0 | size_hint::sub_scalar(at_start(n, k), min_n - k + 1) |
172 | | } |
173 | | Self::Loaded { |
174 | 0 | ref indices, |
175 | 0 | ref cycles, |
176 | | } => { |
177 | 0 | let count = cycles.iter().enumerate().try_fold(0usize, |acc, (i, &c)| { |
178 | 0 | acc.checked_mul(indices.len() - i) |
179 | 0 | .and_then(|count| count.checked_add(c)) |
180 | 0 | }); |
181 | 0 | (count.unwrap_or(usize::MAX), count) |
182 | | } |
183 | 0 | Self::End => (0, Some(0)), |
184 | | } |
185 | 0 | } |
186 | | } |