Skip to content

Commit a81cfcd

Browse files
committed
🚧 Refactor in terms of underlying pure-indices indices streaming iterator.
1 parent 3efe36c commit a81cfcd

File tree

1 file changed

+164
-52
lines changed

1 file changed

+164
-52
lines changed

‎src/cartesian_power.rs

Lines changed: 164 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,137 @@
11
use alloc::vec::Vec;
22
use std::fmt;
33

4+
/// Pseudo-iterator owned by [`CartesianPower`],
5+
/// yielding underlying indices by references to itself,
6+
/// the [streaming iterator](https://docs.rs/streaming-iterator/latest/streaming_iterator/) way.
7+
pub struct Indices {
8+
pow: u32,
9+
// May be incremented by owner on first pass as long as exact value is unknown.
10+
base: usize,
11+
values: Option<Vec<usize>>,
12+
}
13+
14+
impl Indices {
15+
pub fn new(base: usize, pow: u32) -> Self {
16+
Self {
17+
base,
18+
pow,
19+
values: None,
20+
}
21+
}
22+
pub fn next(&mut self) -> Option<&[usize]> {
23+
let Self { base, pow, values } = self;
24+
match (base, pow, values) {
25+
// First iteration with degenerated 0th power.
26+
(_, 0, values @ None) => Some(values.insert(Vec::new())),
27+
28+
// Last degenerated 0th power iteration.
29+
// Use the Some<(empty)Vec> as a flag to alternate between yielding [] or None.
30+
(_, 0, values @ Some(_)) => {
31+
*values = None;
32+
None
33+
}
34+
35+
// Stable iteration in 0-base.
36+
(0, _, _) => None,
37+
38+
// First iteration in the general case.
39+
(_, pow, values @ None) => Some(values.insert(vec![0; *pow as usize])),
40+
41+
// Subsequent iteration in the general case.
42+
(&mut base, _, Some(values)) => {
43+
if values[0] == base {
44+
// Special marker that iteration can start over for a new round.
45+
values[0] = 0;
46+
return Some(values);
47+
}
48+
if inbounds_increment(values, base) {
49+
return Some(values);
50+
}
51+
// Iteration is over.
52+
// Mark a special index value to not fuse the iterator
53+
// and make it possible to cycle through all results again.
54+
values[0] = base;
55+
None
56+
}
57+
}
58+
}
59+
60+
pub fn nth(&mut self, n: usize) -> Option<&[usize]> {
61+
let Self { base, pow, values } = self;
62+
match (base, pow, values, n) {
63+
// First iteration with degenerated 0th power.
64+
(_, 0, values @ None, 0) => {
65+
// Same as .next()
66+
Some(values.insert(Vec::new()))
67+
}
68+
// Saturate.
69+
(_, 0, values @ Some(_), _) => {
70+
*values = None;
71+
None
72+
}
73+
// Stable iteration in 0-base.
74+
(0, _, _, _) => None,
75+
// First iteration in the general case.
76+
(&mut base, pow, values @ None, n) => {
77+
let values = values.insert(vec![0; *pow as usize]);
78+
if inbounds_increment_by(n, values, base) {
79+
return Some(values);
80+
}
81+
// Immediate saturation.
82+
values[0] = base;
83+
None
84+
}
85+
// Subsequent iteration in the general case.
86+
(&mut base, _, Some(values), n) => {
87+
let shift = if values[0] == base {
88+
// Start over for a new round (already counted then).
89+
values[0] = 0;
90+
0
91+
} else {
92+
1
93+
};
94+
if inbounds_increment_by(n + shift, values, base) {
95+
return Some(values);
96+
}
97+
// Immediate re-saturation.
98+
values[0] = base;
99+
None
100+
}
101+
}
102+
}
103+
}
104+
105+
/// Increment indices, returning false in case of overflow.
106+
fn inbounds_increment(indices: &mut [usize], base: usize) -> bool {
107+
for index in indices.iter_mut().rev() {
108+
*index += 1;
109+
if *index < base {
110+
return true;
111+
}
112+
*index = 0; // Wrap and increment left.
113+
}
114+
false
115+
}
116+
117+
/// Increment indices by n, returning false in case of (saturating) overflow.
118+
fn inbounds_increment_by(n: usize, indices: &mut [usize], base: usize) -> bool {
119+
let mut q = n;
120+
for index in indices.iter_mut().rev() {
121+
let s = *index + q;
122+
q = s / base;
123+
*index = s % base;
124+
if q == 0 {
125+
return true;
126+
}
127+
}
128+
// Saturation requires a second pass to reset all indices.
129+
for index in indices.iter_mut() {
130+
*index = 0;
131+
}
132+
false
133+
}
134+
4135
/// An adaptor iterating through all the ordered `n`-length lists of items
5136
/// yielded by the underlying iterator, including repetitions.
6137
///
@@ -66,24 +197,24 @@ where
66197
let pow = *pow as usize;
67198

68199
// (weird 'items @' bindings circumvent NLL limitations, unneeded with polonius)
69-
match (pow, iter, &mut *items) {
200+
match (&mut *items, pow, iter) {
70201
// First iteration with degenerated 0th power.
71-
(0, Some(_), items @ None) => {
202+
(items @ None, 0, Some(_)) => {
72203
self.iter = None; // Forget about underlying iteration immediately.
73204
let empty = items.insert(Vec::new()); // Raise this value as a boolean flag.
74205
Some((indices, empty)) // Yield empty list.
75206
}
76207

77208
// Subsequent degenerated 0th power iteration.
78209
// Use the Some<(empty)Vec> as a flag to alternate between yielding [] or None.
79-
(0, None, items @ Some(_)) => {
210+
(items @ Some(_), 0, None) => {
80211
*items = None;
81212
None
82213
}
83-
(0, None, items @ None) => Some((indices, items.insert(Vec::new()))),
214+
(items @ None, 0, None) => Some((indices, items.insert(Vec::new()))),
84215

85216
// First iteration in the general case.
86-
(pow, Some(it), items @ None) => {
217+
(items @ None, pow, Some(it)) => {
87218
// Check whether there is at least one element in the iterator.
88219
if let Some(first) = it.next() {
89220
items // Collect it.
@@ -104,10 +235,10 @@ where
104235
}
105236

106237
// Stable iteration in the degenerated case 'base = 0'.
107-
(_, None, None) => None,
238+
(None, _, None) => None,
108239

109240
// Subsequent iteration in the general case.
110-
(pow, Some(it), Some(items)) => {
241+
(Some(items), pow, Some(it)) => {
111242
// We are still unsure whether all items have been collected.
112243
// As a consequence, the exact value of 'base' is still uncertain,
113244
// but then we know that indices haven't started wrapping around yet.
@@ -133,15 +264,15 @@ where
133264
}
134265

135266
// Subsequent iteration in the general case after all items have been collected.
136-
(_, None, Some(items)) => {
267+
(Some(items), _, None) => {
137268
let base = items.len();
138269
if indices[0] == base {
139270
// Special marker that iteration can start over for a new round.
140271
indices[0] = 0;
141272
return Some((indices, items));
142273
}
143274
// Keep yielding items list, incrementing indices rightmost first.
144-
if Self::inbounds_increment(indices, base) {
275+
if inbounds_increment(indices, base) {
145276
return Some((indices, items));
146277
}
147278
// Iteration is over.
@@ -153,36 +284,6 @@ where
153284
}
154285
}
155286

156-
/// Increment indices, returning false in case of overflow.
157-
fn inbounds_increment(indices: &mut [usize], base: usize) -> bool {
158-
for index in indices.iter_mut().rev() {
159-
*index += 1;
160-
if *index < base {
161-
return true;
162-
}
163-
*index = 0; // Wrap and increment left.
164-
}
165-
false
166-
}
167-
168-
/// Increment indices by n, returning false in case of (saturating) overflow.
169-
fn inbounds_increment_by(n: usize, indices: &mut [usize], base: usize) -> bool {
170-
let mut q = n;
171-
for index in indices.iter_mut().rev() {
172-
let s = *index + q;
173-
q = s / base;
174-
*index = s % base;
175-
if q == 0 {
176-
return true;
177-
}
178-
}
179-
// Saturation requires a second pass to reset all indices.
180-
for index in indices.iter_mut() {
181-
*index = 0;
182-
}
183-
false
184-
}
185-
186287
/// Same as [`increment_indices`], but does n increments at once.
187288
/// The iterator is cycling, but `.nth()` does not 'wrap'
188289
/// and 'saturates' to None instead.
@@ -196,33 +297,33 @@ where
196297

197298
let pow = *pow as usize;
198299

199-
match (pow, iter, &mut *items, n) {
300+
match (&mut *items, pow, iter, n) {
200301
// First iteration with degenerated 0th power.
201-
(0, Some(_), items @ None, 0) => {
302+
(items @ None, 0, Some(_), 0) => {
202303
// Same as .next().
203304
self.iter = None;
204305
let empty = items.insert(Vec::new());
205306
Some((indices, empty))
206307
}
207-
(0, Some(_), None, _) => {
308+
(None, 0, Some(_), _) => {
208309
// Saturate.
209310
self.iter = None;
210311
None
211312
}
212313

213314
// Subsequent degenerated 0th power iteration.
214315
// Same as `.next()`.
215-
(0, None, items @ None, 0) => Some((indices, items.insert(Vec::new()))),
316+
(items @ None, 0, None, 0) => Some((indices, items.insert(Vec::new()))),
216317
// Saturate.
217-
(0, None, items, _) => {
318+
(items, 0, None, _) => {
218319
*items = None;
219320
None
220321
}
221322

222323
// First iterations in the general case.
223324
// Possibly this will consume the entire underlying iterator,
224325
// but we need to consume to check.
225-
(pow, Some(it), items @ None, mut remaining) => {
326+
(items @ None, pow, Some(it), mut remaining) => {
226327
if let Some(first) = it.next() {
227328
// There is at least one element in the iterator, prepare collection + indices.
228329
let items = items.insert(Vec::with_capacity(it.size_hint().0));
@@ -246,7 +347,7 @@ where
246347
// Collection completed, but we need to go further.
247348
self.iter = None;
248349
let base = items.len();
249-
if Self::inbounds_increment_by(n, indices, base) {
350+
if inbounds_increment_by(n, indices, base) {
250351
return Some((indices, items));
251352
}
252353
// Immediate saturation.
@@ -261,11 +362,11 @@ where
261362
}
262363

263364
// Stable iteration in the degenerated case 'base = 0'.
264-
(_, None, None, _) => None,
365+
(None, _, None, _) => None,
265366

266367
// Subsequent iteration in the general case.
267368
// Again, immediate saturation is an option.
268-
(pow, Some(it), Some(items), mut remaining) => {
369+
(Some(items), pow, Some(it), mut remaining) => {
269370
if let Some(next) = it.next() {
270371
items.push(next);
271372
loop {
@@ -284,7 +385,7 @@ where
284385
// Collection completed.
285386
self.iter = None;
286387
let base = items.len();
287-
if Self::inbounds_increment_by(n + 1, indices, base) {
388+
if inbounds_increment_by(n + 1, indices, base) {
288389
return Some((indices, items));
289390
}
290391
// Saturate.
@@ -294,7 +395,7 @@ where
294395

295396
// Subsequent iteration in the general case
296397
// after all items have been collected.
297-
(_, None, Some(items), n) => {
398+
(Some(items), _, None, n) => {
298399
let base = items.len();
299400
let shift = if indices[0] == base {
300401
// Start over for a new round (already counted then).
@@ -303,7 +404,7 @@ where
303404
} else {
304405
1
305406
};
306-
if Self::inbounds_increment_by(n + shift, indices, base) {
407+
if inbounds_increment_by(n + shift, indices, base) {
307408
return Some((indices, items));
308409
}
309410
// Immediate re-saturation.
@@ -446,8 +547,19 @@ where
446547
#[cfg(test)]
447548
mod tests {
448549

449-
use crate::Itertools;
550+
use crate::{cartesian_power::Indices, Itertools};
450551

552+
#[test]
553+
fn indices() {
554+
let mut it = Indices::new(3, 2);
555+
for i in 0..30 {
556+
println!("{i}: {:?}", it.next());
557+
}
558+
for i in 0..30 {
559+
println!("{i}: {:?}", it.nth(2));
560+
}
561+
panic!("STOP HERE");
562+
}
451563
#[test]
452564
fn basic() {
453565
fn check(origin: &str, pow: u32, expected: &[&str]) {

0 commit comments

Comments
 (0)