@@ -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