Skip to content

Commit 99de003

Browse files
committed
Use Idx type directly in PermutationState
1 parent 6056b73 commit 99de003

File tree

2 files changed

+45
-32
lines changed

2 files changed

+45
-32
lines changed

src/lazy_buffer.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,15 @@ pub trait ArrayOrVecHelper: BorrowMut<[usize]> {
113113
fn item_from_fn<T, F: Fn(usize) -> T>(len: Self::Length, f: F) -> Self::Item<T>;
114114

115115
fn len(&self) -> Self::Length;
116+
117+
fn from_fn<F: Fn(usize) -> usize>(k: Self::Length, f: F) -> Self;
118+
119+
fn start(len: Self::Length) -> Self
120+
where
121+
Self: Sized,
122+
{
123+
Self::from_fn(len, |i| i)
124+
}
116125
}
117126

118127
impl ArrayOrVecHelper for Vec<usize> {
@@ -133,6 +142,10 @@ impl ArrayOrVecHelper for Vec<usize> {
133142
fn len(&self) -> Self::Length {
134143
self.len()
135144
}
145+
146+
fn from_fn<F: Fn(usize) -> usize>(k: Self::Length, f: F) -> Self {
147+
(0..k).map(f).collect()
148+
}
136149
}
137150

138151
impl<const K: usize> ArrayOrVecHelper for [usize; K] {
@@ -153,4 +166,8 @@ impl<const K: usize> ArrayOrVecHelper for [usize; K] {
153166
fn len(&self) -> Self::Length {
154167
ConstUsize::<K>
155168
}
169+
170+
fn from_fn<F: Fn(usize) -> usize>(_len: Self::Length, f: F) -> Self {
171+
std::array::from_fn(f)
172+
}
156173
}

src/permutations.rs

Lines changed: 28 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,9 @@ enum PermutationState<Idx: ArrayOrVecHelper> {
3333
/// No permutation generated yet.
3434
Start { k: Idx::Length },
3535
/// Values from the iterator are not fully loaded yet so `n` is still unknown.
36-
Buffered { k: Idx::Length, min_n: usize },
36+
Buffered { indices: Idx, min_n: usize },
3737
/// All values from the iterator are known so `n` is known.
38-
Loaded {
39-
indices: Box<[usize]>,
40-
cycles: Box<[usize]>, // TODO Should be Idx::Item<usize>
41-
k: Idx::Length, // TODO Should be inferred from cycles
42-
},
38+
Loaded { indices: Box<[usize]>, cycles: Idx },
4339
/// No permutation left to generate.
4440
End,
4541
}
@@ -80,47 +76,43 @@ where
8076
return None;
8177
}
8278
*state = PermutationState::Buffered {
83-
k,
79+
indices: Idx::start(k),
8480
min_n: k.value(),
8581
};
8682
}
8783
Some(Idx::item_from_fn(k, |i| vals[i].clone()))
8884
}
89-
PermutationState::Buffered { k, min_n } => {
85+
PermutationState::Buffered { indices, min_n } => {
86+
let k = indices.len();
9087
if vals.get_next() {
91-
// TODO This is ugly. Maybe working on indices is better?
92-
let item = Idx::item_from_fn(*k, |i| {
93-
vals[if i == k.value() - 1 { *min_n } else { i }].clone()
94-
});
88+
indices.borrow_mut()[k.value() - 1] += 1;
9589
*min_n += 1;
96-
Some(item)
90+
Some(indices.extract_item(vals))
9791
} else {
9892
let n = *min_n;
9993
let prev_iteration_count = n - k.value() + 1;
10094
let mut indices: Box<[_]> = (0..n).collect();
101-
let mut cycles: Box<[_]> = (n - k.value()..n).rev().collect();
95+
let mut cycles = Idx::from_fn(k, |i| n - 1 - i);
10296
// Advance the state to the correct point.
10397
for _ in 0..prev_iteration_count {
104-
if advance(&mut indices, &mut cycles) {
98+
if advance(&mut indices, cycles.borrow_mut()) {
10599
*state = PermutationState::End;
106100
return None;
107101
}
108102
}
109-
let item = Idx::item_from_fn(*k, |i| vals[indices[i]].clone());
110-
*state = PermutationState::Loaded {
111-
indices,
112-
cycles,
113-
k: *k,
114-
};
103+
let item = Idx::item_from_fn(k, |i| vals[indices[i]].clone());
104+
*state = PermutationState::Loaded { indices, cycles };
115105
Some(item)
116106
}
117107
}
118-
PermutationState::Loaded { indices, cycles, k } => {
119-
if advance(indices, cycles) {
108+
PermutationState::Loaded { indices, cycles } => {
109+
if advance(indices, cycles.borrow_mut()) {
120110
*state = PermutationState::End;
121111
return None;
122112
}
123-
Some(Idx::item_from_fn(*k, |i| vals[indices[i]].clone()))
113+
Some(Idx::item_from_fn(cycles.len(), |i| {
114+
vals[indices[i]].clone()
115+
}))
124116
}
125117
PermutationState::End => None,
126118
}
@@ -173,22 +165,26 @@ impl<Idx: ArrayOrVecHelper> PermutationState<Idx> {
173165
let total = (n - k.value() + 1..=n).try_fold(1usize, |acc, i| acc.checked_mul(i));
174166
(total.unwrap_or(usize::MAX), total)
175167
};
176-
match *self {
168+
match self {
177169
Self::Start { k } if n < k.value() => (0, Some(0)),
178-
Self::Start { k } => at_start(n, k),
179-
Self::Buffered { k, min_n } => {
170+
Self::Start { k } => at_start(n, *k),
171+
Self::Buffered { indices, min_n } => {
172+
let k = indices.len();
180173
// Same as `Start` minus the previously generated items.
181174
size_hint::sub_scalar(at_start(n, k), min_n - k.value() + 1)
182175
}
183176
Self::Loaded {
184177
ref indices,
185178
ref cycles,
186-
k: _,
187179
} => {
188-
let count = cycles.iter().enumerate().try_fold(0usize, |acc, (i, &c)| {
189-
acc.checked_mul(indices.len() - i)
190-
.and_then(|count| count.checked_add(c))
191-
});
180+
let count = cycles
181+
.borrow()
182+
.iter()
183+
.enumerate()
184+
.try_fold(0usize, |acc, (i, &c)| {
185+
acc.checked_mul(indices.len() - i)
186+
.and_then(|count| count.checked_add(c))
187+
});
192188
(count.unwrap_or(usize::MAX), count)
193189
}
194190
Self::End => (0, Some(0)),

0 commit comments

Comments
 (0)