1
1
use alloc:: vec:: Vec ;
2
2
use std:: fmt;
3
- use std:: iter:: FusedIterator ;
4
3
5
4
/// An adaptor iterating through all the ordered `n`-length lists of items
6
5
/// yielded by the underlying iterator, including repetitions.
15
14
I :: Item : Clone ,
16
15
{
17
16
pow : usize ,
18
- iter : Option < I > , // Inner iterator. Forget once consumed after 'base' iterations.
19
- items : Vec < I :: Item > , // Fill from iter. Clear once adaptor is exhausted. Final length is 'base'.
20
- indices : Vec < usize > , // Indices just yielded. Clear once adaptor is exhausted. Length is 'pow'.
17
+ iter : Option < I > , // Inner iterator. Forget once consumed after 'base' iterations.
18
+ items : Option < Vec < I :: Item > > , // Fill from iter. Final length is 'base'.
19
+ // None means that collection has not started yet.
20
+ // Some(empty) means that collection would have started but pow = 0.
21
+
22
+ // Indices just yielded. Length is 'pow'.
23
+ // 0 0 .. 0 0 means that the first combination has been yielded.
24
+ // 0 0 .. 0 1 means that the second combination has been yielded.
25
+ // m m .. m m means that the last combination has just been yielded (m = base - 1).
26
+ // b 0 .. 0 0 means that 'None' has just been yielded (b = base).
27
+ // The latter is a special value marking the renewal of the iterator,
28
+ // which can cycle again through another full round, ad libitum.
29
+ indices : Vec < usize > ,
21
30
}
22
31
23
32
/// Create a new `CartesianPower` from an iterator of clonables.
29
38
CartesianPower {
30
39
pow,
31
40
iter : Some ( iter) ,
32
- items : Vec :: new ( ) ,
41
+ items : None ,
33
42
indices : Vec :: new ( ) ,
34
43
}
35
44
}
@@ -53,70 +62,99 @@ where
53
62
items,
54
63
indices,
55
64
} = self ;
56
- match ( * pow, iter, items. len ( ) ) {
57
- // Final stable state: underlying iterator and items forgotten.
58
- ( _, None , 0 ) => None ,
65
+ println ! (
66
+ "^{pow}: {} {indices:?}\t \t {:?}" ,
67
+ if iter. is_some( ) { 'S' } else { 'N' } ,
68
+ items. as_ref( ) . map( Vec :: len)
69
+ ) ;
59
70
60
- // Degenerated 0th power iteration.
61
- ( 0 , Some ( _) , _) => {
62
- self . iter = None ; // Forget without even consuming.
63
- Some ( ( indices, items) )
71
+ // (weird 'items @' bindings circumvent NLL limitations, unneeded with polonius)
72
+ match ( * pow, iter, & mut * items) {
73
+ // First iteration with degenerated 0th power.
74
+ ( 0 , Some ( _) , items @ None ) => {
75
+ self . iter = None ; // Forget about underlying iteration immediately.
76
+ let empty = items. insert ( Vec :: new ( ) ) ; // Raise this value as a boolean flag.
77
+ Some ( ( indices, empty) ) // Yield empty list.
64
78
}
65
79
66
- ( pow, Some ( it) , 0 ) => {
80
+ // Subsequent degenerated 0th power iteration.
81
+ // Use the Some<(empty)Vec> as a flag to alternate between yielding [] or None.
82
+ ( 0 , None , items @ Some ( _) ) => {
83
+ * items = None ;
84
+ None
85
+ }
86
+ ( 0 , None , items @ None ) => Some ( ( indices, items. insert ( Vec :: new ( ) ) ) ) ,
87
+
88
+ // First iteration in the general case.
89
+ ( pow, Some ( it) , items @ None ) => {
67
90
// Check whether there is at least one element in the iterator.
68
91
if let Some ( first) = it. next ( ) {
69
- // Allocate buffer to hold items about to be yielded .
70
- items . reserve_exact ( it. size_hint ( ) . 0 ) ;
71
- items . push ( first) ;
72
- // Same for indices to be yielded.
92
+ items // Collect it .
93
+ . insert ( Vec :: with_capacity ( it. size_hint ( ) . 0 ) )
94
+ . push ( first) ;
95
+ // Prepare indices to be yielded.
73
96
indices. reserve_exact ( pow) ;
74
97
for _ in 0 ..pow {
75
98
indices. push ( 0 ) ;
76
99
}
77
- return Some ( ( indices, items) ) ;
100
+ Some ( ( indices, items. as_ref ( ) . unwrap ( ) ) )
101
+ } else {
102
+ // Degenerated iteration over an empty set:
103
+ // 'base = 0', yet with non-null power.
104
+ self . iter = None ;
105
+ None
78
106
}
79
- // Degenerated iteration over an empty set, yet with non-null power.
80
- self . iter = None ;
81
- None
82
107
}
83
108
84
- ( pow, Some ( it) , base) => {
109
+ // Stable iteration in the degenerated case 'base = 0'.
110
+ ( _, None , None ) => None ,
111
+
112
+ // Subsequent iteration in the general case.
113
+ ( pow, Some ( it) , Some ( items) ) => {
85
114
// We are still unsure whether all items have been collected.
86
- // As a consequence, 'base' is still uncertain,
115
+ // As a consequence, the exact value of 'base' is still uncertain,
87
116
// but then we know that indices haven't started wrapping around yet.
88
117
if let Some ( next) = it. next ( ) {
89
118
items. push ( next) ;
90
119
indices[ pow - 1 ] += 1 ;
91
120
return Some ( ( indices, items) ) ;
92
121
}
93
122
94
- // All items have just been collected .
123
+ // The item collected on previous call was the last one .
95
124
self . iter = None ;
125
+ let base = items. len ( ) ; // Definitive 'base' value.
96
126
if base == 1 || pow == 1 {
97
- // End of iteration.
98
- items. clear ( ) ;
99
- indices. clear ( ) ;
127
+ // Early end of singleton iteration.
128
+ indices[ 0 ] = base; // Mark to cycle again on next iteration.
100
129
return None ;
101
130
}
102
131
103
132
// First wrap around.
104
133
indices[ pow - 1 ] = 0 ;
105
- indices[ pow - 2 ] + = 1 ;
134
+ indices[ pow - 2 ] = 1 ;
106
135
Some ( ( indices, items) )
107
136
}
108
137
109
- ( _, None , b) => {
138
+ // Subsequent iteration in the general case after all items have been collected.
139
+ ( _, None , Some ( items) ) => {
140
+ let base = items. len ( ) ;
141
+ if indices[ 0 ] == base {
142
+ // Special marker that iteration can start over for a new round.
143
+ indices[ 0 ] = 0 ;
144
+ return Some ( ( indices, items) ) ;
145
+ }
110
146
// Keep yielding items list, incrementing indices rightmost first.
111
147
for index in indices. iter_mut ( ) . rev ( ) {
112
148
* index += 1 ;
113
- if * index < b {
149
+ if * index < base {
114
150
return Some ( ( indices, items) ) ;
115
151
}
116
152
* index = 0 ; // Wrap and increment left.
117
153
}
118
- items. clear ( ) ;
119
- indices. clear ( ) ;
154
+ // Iteration is over.
155
+ // Mark a special index value to not fuse the iterator
156
+ // and make it possible to cycle through all results again.
157
+ indices[ 0 ] = base;
120
158
None
121
159
}
122
160
}
@@ -187,13 +225,6 @@ where
187
225
}
188
226
}
189
227
190
- impl < I > FusedIterator for CartesianPower < I >
191
- where
192
- I : Iterator ,
193
- I :: Item : Clone ,
194
- {
195
- }
196
-
197
228
#[ cfg( test) ]
198
229
mod tests {
199
230
//! Use chars and string to ease testing of every yielded iterator values.
@@ -202,41 +233,50 @@ mod tests {
202
233
use crate :: Itertools ;
203
234
use core:: str:: Chars ;
204
235
205
- fn check_fused ( mut exhausted_it : CartesianPower < Chars > , context : String ) {
206
- for i in 0 ..100 {
207
- let act = exhausted_it. next ( ) ;
208
- assert ! (
209
- act. is_none( ) ,
210
- "Iteration {} after expected exhaustion of {} \
211
- yielded {:?} instead of None. ",
212
- i,
213
- context,
214
- act,
215
- ) ;
216
- }
217
- }
218
-
219
236
#[ test]
220
237
fn basic ( ) {
221
238
fn check ( origin : & str , pow : usize , expected : & [ & str ] ) {
222
- let mut it = origin. chars ( ) . cartesian_power ( pow) ;
223
- let mut i = 0 ;
224
- for exp in expected {
225
- let act = it. next ( ) ;
226
- if act != Some ( exp. chars ( ) . collect ( ) ) {
227
- panic ! (
228
- "Failed iteration {} for {:?}^{}. \
229
- Expected {:?}, got {:?} instead.",
230
- i, origin, pow, exp, act,
231
- ) ;
239
+ println ! ( "================== ({origin:?}^{pow})" ) ;
240
+ let mut it_act = origin. chars ( ) . cartesian_power ( pow) ;
241
+ // Check thrice that it's cycling.
242
+ for r in 1 ..=3 {
243
+ println ! ( "- - {r} - - - - - -" ) ;
244
+ let mut it_exp = expected. iter ( ) ;
245
+ let mut i = 0 ;
246
+ loop {
247
+ match ( it_exp. next ( ) , it_act. next ( ) ) {
248
+ ( Some ( exp) , Some ( act) ) => {
249
+ if act != exp. chars ( ) . collect :: < Vec < _ > > ( ) {
250
+ panic ! (
251
+ "Failed iteration {} (repetition {}) for {:?}^{}. \
252
+ Expected {:?}, got {:?} instead.",
253
+ i, r, origin, pow, exp, act,
254
+ ) ;
255
+ }
256
+ i += 1 ;
257
+ }
258
+ ( None , Some ( act) ) => {
259
+ panic ! (
260
+ "Failed iteration {} (repetition {}) for {:?}^{}. \
261
+ Expected None, got {:?} instead.",
262
+ i, r, origin, pow, act,
263
+ ) ;
264
+ }
265
+ ( Some ( exp) , None ) => {
266
+ panic ! (
267
+ "Failed iteration {} (repetition {}) for {:?}^{}. \
268
+ Expected {:?}, got None instead.",
269
+ i, r, origin, pow, exp,
270
+ ) ;
271
+ }
272
+ ( None , None ) => break ,
273
+ }
232
274
}
233
- i += 1 ;
234
275
}
235
- check_fused ( it, format ! ( "iteration {} or {:?}^{}" , i, origin, pow) ) ;
236
276
}
237
277
238
278
// Empty underlying iterator.
239
- check ( "" , 0 , & [ "" ] ) ;
279
+ check ( "" , 0 , & [ "" ] ) ; // 0^0 = 1.
240
280
check ( "" , 1 , & [ ] ) ;
241
281
check ( "" , 2 , & [ ] ) ;
242
282
check ( "" , 3 , & [ ] ) ;
@@ -281,42 +321,30 @@ mod tests {
281
321
fn check ( origin : & str , pow : usize , expected : & [ ( usize , Option < & str > ) ] ) {
282
322
let mut it = origin. chars ( ) . cartesian_power ( pow) ;
283
323
let mut total_n = Vec :: new ( ) ;
284
- for & ( n, exp) in expected {
285
- let act = it. nth ( n) ;
286
- total_n. push ( n) ;
287
- if act != exp. map ( |s| s. chars ( ) . collect :: < Vec < _ > > ( ) ) {
288
- panic ! (
289
- "Failed nth({}) iteration for {:?}^{}. \
290
- Expected {:?}, got {:?} instead.",
291
- total_n
292
- . iter( )
293
- . map( ToString :: to_string)
294
- . collect:: <Vec <_>>( )
295
- . join( ", " ) ,
296
- origin,
297
- pow,
298
- exp,
299
- act,
300
- ) ;
324
+ for r in 1 ..=3 {
325
+ for & ( n, exp) in expected {
326
+ let act = it. nth ( n) ;
327
+ total_n. push ( n) ;
328
+ if act != exp. map ( |s| s. chars ( ) . collect :: < Vec < _ > > ( ) ) {
329
+ panic ! (
330
+ "Failed nth({}) iteration (repetition {}) for {:?}^{}. \
331
+ Expected {:?}, got {:?} instead.",
332
+ total_n
333
+ . iter( )
334
+ . map( ToString :: to_string)
335
+ . collect:: <Vec <_>>( )
336
+ . join( ", " ) ,
337
+ r,
338
+ origin,
339
+ pow,
340
+ exp,
341
+ act
342
+ ) ;
343
+ }
301
344
}
302
345
}
303
- check_fused (
304
- it,
305
- format ! (
306
- "nth({}) iteration of {:?}^{}" ,
307
- total_n
308
- . iter( )
309
- . map( ToString :: to_string)
310
- . collect:: <Vec <_>>( )
311
- . join( ", " ) ,
312
- origin,
313
- pow
314
- ) ,
315
- ) ;
316
346
}
317
347
318
- // HERE: make it work with the new implementation.
319
-
320
348
// Check degenerated cases.
321
349
check ( "" , 0 , & [ ( 0 , Some ( "" ) ) , ( 0 , None ) ] ) ;
322
350
check ( "" , 0 , & [ ( 0 , Some ( "" ) ) , ( 1 , None ) ] ) ;
0 commit comments