Skip to content

Commit 98b79de

Browse files
phimuemueronnodas
authored andcommitted
Try to use PoolIndex for permutations
1 parent aa90cbb commit 98b79de

File tree

2 files changed

+28
-14
lines changed

2 files changed

+28
-14
lines changed

src/combinations.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ pub trait PoolIndex: BorrowMut<[usize]> {
6767
where
6868
I::Item: Clone;
6969

70+
fn from_fn<T, F: Fn(usize)->T>(k: Self::Length, f: F) -> Self::Item<T>;
71+
7072
fn len(&self) -> Self::Length;
7173
}
7274

@@ -80,6 +82,10 @@ impl PoolIndex for Vec<usize> {
8082
{
8183
pool.get_at(self)
8284
}
85+
86+
fn from_fn<T, F: Fn(usize)->T>(k: Self::Length, f: F) -> Self::Item<T> {
87+
(0..k).map(f).collect()
88+
}
8389

8490
fn len(&self) -> Self::Length {
8591
self.len()
@@ -97,6 +103,10 @@ impl<const K: usize> PoolIndex for [usize; K] {
97103
pool.get_array(*self)
98104
}
99105

106+
fn from_fn<T, F: Fn(usize)->T>(_k: Self::Length, f: F) -> Self::Item<T> {
107+
std::array::from_fn(f)
108+
}
109+
100110
fn len(&self) -> Self::Length {
101111
ConstUsize::<K>
102112
}

src/permutations.rs

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use alloc::boxed::Box;
22
use alloc::vec::Vec;
33
use std::fmt;
4-
use std::iter::once;
54
use std::iter::FusedIterator;
65

76
use super::lazy_buffer::LazyBuffer;
@@ -39,7 +38,8 @@ enum PermutationState<Idx: PoolIndex> {
3938
/// All values from the iterator are known so `n` is known.
4039
Loaded {
4140
indices: Box<[usize]>,
42-
cycles: Box<[usize]>,
41+
cycles: Box<[usize]>, // TODO Should be Idx::Item<usize>
42+
k: Idx::Length, // TODO Should be inferred from cycles
4343
},
4444
/// No permutation left to generate.
4545
End,
@@ -66,7 +66,7 @@ where
6666
I: Iterator,
6767
I::Item: Clone,
6868
{
69-
type Item = Vec<I::Item>;
69+
type Item = Idx::Item<I::Item>;
7070

7171
fn next(&mut self) -> Option<Self::Item> {
7272
let Self { vals, state } = self;
@@ -82,14 +82,18 @@ where
8282
}
8383
*state = PermutationState::Buffered { k, min_n: k.value() };
8484
}
85-
Some(vals[0..k.value()].to_vec())
85+
Some(Idx::from_fn(k, |i| vals[i].clone()))
8686
}
87-
PermutationState::Buffered { ref k, min_n } => {
87+
PermutationState::Buffered { k, min_n } => {
8888
if vals.get_next() {
89-
let item = (0..k.value() - 1)
90-
.chain(once(*min_n))
91-
.map(|i| vals[i].clone())
92-
.collect();
89+
// TODO This is ugly. Maybe working on indices is better?
90+
let item = Idx::from_fn(*k, |i| {
91+
vals[if i==k.value()-1 {
92+
*min_n
93+
} else {
94+
i
95+
}].clone()
96+
});
9397
*min_n += 1;
9498
Some(item)
9599
} else {
@@ -104,18 +108,17 @@ where
104108
return None;
105109
}
106110
}
107-
let item = vals.get_at(&indices[0..k.value()]);
108-
*state = PermutationState::Loaded { indices, cycles };
111+
let item = Idx::from_fn(*k, |i| vals[indices[i]].clone());
112+
*state = PermutationState::Loaded { indices, cycles, k:*k };
109113
Some(item)
110114
}
111115
}
112-
PermutationState::Loaded { indices, cycles } => {
116+
PermutationState::Loaded { indices, cycles, k} => {
113117
if advance(indices, cycles) {
114118
*state = PermutationState::End;
115119
return None;
116120
}
117-
let k = cycles.len();
118-
Some(vals.get_at(&indices[0..k]))
121+
Some(Idx::from_fn(*k, |i| vals[indices[i]].clone()))
119122
}
120123
PermutationState::End => None,
121124
}
@@ -178,6 +181,7 @@ impl<Idx: PoolIndex> PermutationState<Idx> {
178181
Self::Loaded {
179182
ref indices,
180183
ref cycles,
184+
k: _,
181185
} => {
182186
let count = cycles.iter().enumerate().try_fold(0usize, |acc, (i, &c)| {
183187
acc.checked_mul(indices.len() - i)

0 commit comments

Comments
 (0)