Skip to content

Commit aa90cbb

Browse files
phimuemueronnodas
authored andcommitted
Express some things via PoolIndex/MaybeConstUsize
1 parent 5826470 commit aa90cbb

File tree

1 file changed

+33
-28
lines changed

1 file changed

+33
-28
lines changed

src/permutations.rs

Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,32 +6,36 @@ use std::iter::FusedIterator;
66

77
use super::lazy_buffer::LazyBuffer;
88
use crate::size_hint::{self, SizeHint};
9+
use crate::combinations::{MaybeConstUsize, PoolIndex};
10+
11+
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
12+
pub struct PermutationsGeneric<I: Iterator, Idx: PoolIndex> {
13+
vals: LazyBuffer<I>,
14+
state: PermutationState<Idx>,
15+
}
916

1017
/// An iterator adaptor that iterates through all the `k`-permutations of the
1118
/// elements from an iterator.
1219
///
1320
/// See [`.permutations()`](crate::Itertools::permutations) for
1421
/// 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-
}
22+
pub type Permutations<I> = PermutationsGeneric<I, Vec<usize>>;
2023

21-
impl<I> Clone for Permutations<I>
24+
impl<I, Idx> Clone for PermutationsGeneric<I, Idx>
2225
where
2326
I: Clone + Iterator,
2427
I::Item: Clone,
28+
Idx: Clone + PoolIndex,
2529
{
2630
clone_fields!(vals, state);
2731
}
2832

2933
#[derive(Clone, Debug)]
30-
enum PermutationState {
34+
enum PermutationState<Idx: PoolIndex> {
3135
/// No permutation generated yet.
32-
Start { k: usize },
36+
Start { k: Idx::Length },
3337
/// Values from the iterator are not fully loaded yet so `n` is still unknown.
34-
Buffered { k: usize, min_n: usize },
38+
Buffered { k: Idx::Length, min_n: usize },
3539
/// All values from the iterator are known so `n` is known.
3640
Loaded {
3741
indices: Box<[usize]>,
@@ -41,12 +45,13 @@ enum PermutationState {
4145
End,
4246
}
4347

44-
impl<I> fmt::Debug for Permutations<I>
48+
impl<I, Idx: PoolIndex> fmt::Debug for PermutationsGeneric<I, Idx>
4549
where
4650
I: Iterator + fmt::Debug,
4751
I::Item: fmt::Debug,
52+
Idx: fmt::Debug,
4853
{
49-
debug_fmt_fields!(Permutations, vals, state);
54+
debug_fmt_fields!(PermutationsGeneric, vals, state);
5055
}
5156

5257
pub fn permutations<I: Iterator>(iter: I, k: usize) -> Permutations<I> {
@@ -56,7 +61,7 @@ pub fn permutations<I: Iterator>(iter: I, k: usize) -> Permutations<I> {
5661
}
5762
}
5863

59-
impl<I> Iterator for Permutations<I>
64+
impl<I, Idx: PoolIndex> Iterator for PermutationsGeneric<I, Idx>
6065
where
6166
I: Iterator,
6267
I::Item: Clone,
@@ -67,39 +72,39 @@ where
6772
let Self { vals, state } = self;
6873
match state {
6974
&mut PermutationState::Start { k } => {
70-
if k == 0 {
75+
if k.value() == 0 {
7176
*state = PermutationState::End;
7277
} else {
73-
vals.prefill(k);
74-
if vals.len() != k {
78+
vals.prefill(k.value());
79+
if vals.len() != k.value() {
7580
*state = PermutationState::End;
7681
return None;
7782
}
78-
*state = PermutationState::Buffered { k, min_n: k };
83+
*state = PermutationState::Buffered { k, min_n: k.value() };
7984
}
80-
Some(vals[0..k].to_vec())
85+
Some(vals[0..k.value()].to_vec())
8186
}
8287
PermutationState::Buffered { ref k, min_n } => {
8388
if vals.get_next() {
84-
let item = (0..*k - 1)
89+
let item = (0..k.value() - 1)
8590
.chain(once(*min_n))
8691
.map(|i| vals[i].clone())
8792
.collect();
8893
*min_n += 1;
8994
Some(item)
9095
} else {
9196
let n = *min_n;
92-
let prev_iteration_count = n - *k + 1;
97+
let prev_iteration_count = n - k.value() + 1;
9398
let mut indices: Box<[_]> = (0..n).collect();
94-
let mut cycles: Box<[_]> = (n - k..n).rev().collect();
99+
let mut cycles: Box<[_]> = (n - k.value()..n).rev().collect();
95100
// Advance the state to the correct point.
96101
for _ in 0..prev_iteration_count {
97102
if advance(&mut indices, &mut cycles) {
98103
*state = PermutationState::End;
99104
return None;
100105
}
101106
}
102-
let item = vals.get_at(&indices[0..*k]);
107+
let item = vals.get_at(&indices[0..k.value()]);
103108
*state = PermutationState::Loaded { indices, cycles };
104109
Some(item)
105110
}
@@ -130,7 +135,7 @@ where
130135
}
131136
}
132137

133-
impl<I> FusedIterator for Permutations<I>
138+
impl<I, Idx: PoolIndex> FusedIterator for PermutationsGeneric<I, Idx>
134139
where
135140
I: Iterator,
136141
I::Item: Clone,
@@ -155,20 +160,20 @@ fn advance(indices: &mut [usize], cycles: &mut [usize]) -> bool {
155160
true
156161
}
157162

158-
impl PermutationState {
163+
impl<Idx: PoolIndex> PermutationState<Idx> {
159164
fn size_hint_for(&self, n: usize) -> SizeHint {
160165
// At the beginning, there are `n!/(n-k)!` items to come.
161-
let at_start = |n, k| {
162-
debug_assert!(n >= k);
163-
let total = (n - k + 1..=n).try_fold(1usize, |acc, i| acc.checked_mul(i));
166+
let at_start = |n, k: Idx::Length| {
167+
debug_assert!(n >= k.value());
168+
let total = (n - k.value() + 1..=n).try_fold(1usize, |acc, i| acc.checked_mul(i));
164169
(total.unwrap_or(usize::MAX), total)
165170
};
166171
match *self {
167-
Self::Start { k } if n < k => (0, Some(0)),
172+
Self::Start { k } if n < k.value() => (0, Some(0)),
168173
Self::Start { k } => at_start(n, k),
169174
Self::Buffered { k, min_n } => {
170175
// Same as `Start` minus the previously generated items.
171-
size_hint::sub_scalar(at_start(n, k), min_n - k + 1)
176+
size_hint::sub_scalar(at_start(n, k), min_n - k.value() + 1)
172177
}
173178
Self::Loaded {
174179
ref indices,

0 commit comments

Comments
 (0)