@@ -33,13 +33,9 @@ enum PermutationState<Idx: ArrayOrVecHelper> {
33
33
/// No permutation generated yet.
34
34
Start { k : Idx :: Length } ,
35
35
/// 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 } ,
37
37
/// 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 } ,
43
39
/// No permutation left to generate.
44
40
End ,
45
41
}
@@ -80,47 +76,43 @@ where
80
76
return None ;
81
77
}
82
78
* state = PermutationState :: Buffered {
83
- k ,
79
+ indices : Idx :: start ( k ) ,
84
80
min_n : k. value ( ) ,
85
81
} ;
86
82
}
87
83
Some ( Idx :: item_from_fn ( k, |i| vals[ i] . clone ( ) ) )
88
84
}
89
- PermutationState :: Buffered { k, min_n } => {
85
+ PermutationState :: Buffered { indices, min_n } => {
86
+ let k = indices. len ( ) ;
90
87
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 ;
95
89
* min_n += 1 ;
96
- Some ( item )
90
+ Some ( indices . extract_item ( vals ) )
97
91
} else {
98
92
let n = * min_n;
99
93
let prev_iteration_count = n - k. value ( ) + 1 ;
100
94
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 ) ;
102
96
// Advance the state to the correct point.
103
97
for _ in 0 ..prev_iteration_count {
104
- if advance ( & mut indices, & mut cycles) {
98
+ if advance ( & mut indices, cycles. borrow_mut ( ) ) {
105
99
* state = PermutationState :: End ;
106
100
return None ;
107
101
}
108
102
}
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 } ;
115
105
Some ( item)
116
106
}
117
107
}
118
- PermutationState :: Loaded { indices, cycles, k } => {
119
- if advance ( indices, cycles) {
108
+ PermutationState :: Loaded { indices, cycles } => {
109
+ if advance ( indices, cycles. borrow_mut ( ) ) {
120
110
* state = PermutationState :: End ;
121
111
return None ;
122
112
}
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
+ } ) )
124
116
}
125
117
PermutationState :: End => None ,
126
118
}
@@ -173,22 +165,26 @@ impl<Idx: ArrayOrVecHelper> PermutationState<Idx> {
173
165
let total = ( n - k. value ( ) + 1 ..=n) . try_fold ( 1usize , |acc, i| acc. checked_mul ( i) ) ;
174
166
( total. unwrap_or ( usize:: MAX ) , total)
175
167
} ;
176
- match * self {
168
+ match self {
177
169
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 ( ) ;
180
173
// Same as `Start` minus the previously generated items.
181
174
size_hint:: sub_scalar ( at_start ( n, k) , min_n - k. value ( ) + 1 )
182
175
}
183
176
Self :: Loaded {
184
177
ref indices,
185
178
ref cycles,
186
- k : _,
187
179
} => {
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
+ } ) ;
192
188
( count. unwrap_or ( usize:: MAX ) , count)
193
189
}
194
190
Self :: End => ( 0 , Some ( 0 ) ) ,
0 commit comments