Skip to content

Commit 2ffbd31

Browse files
committed
Drop done and needless heap alocation
1 parent 5a038e4 commit 2ffbd31

File tree

1 file changed

+33
-25
lines changed

1 file changed

+33
-25
lines changed

src/combinations.rs

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,22 @@ pub struct Combinations<I: Iterator> {
1414
indices: Vec<usize>,
1515
pool: LazyBuffer<I>,
1616
first: bool,
17-
done: bool,
1817
}
1918

2019
impl<I> Clone for Combinations<I>
2120
where
2221
I: Clone + Iterator,
2322
I::Item: Clone,
2423
{
25-
clone_fields!(indices, pool, first, done);
24+
clone_fields!(indices, pool, first);
2625
}
2726

2827
impl<I> fmt::Debug for Combinations<I>
2928
where
3029
I: Iterator + fmt::Debug,
3130
I::Item: fmt::Debug,
3231
{
33-
debug_fmt_fields!(Combinations, indices, pool, first, done);
32+
debug_fmt_fields!(Combinations, indices, pool, first);
3433
}
3534

3635
/// Create a new `Combinations` from a clonable iterator.
@@ -42,7 +41,6 @@ where
4241
indices: (0..k).collect(),
4342
pool: LazyBuffer::new(iter),
4443
first: true,
45-
done: false,
4644
}
4745
}
4846

@@ -72,7 +70,6 @@ impl<I: Iterator> Combinations<I> {
7270
/// elements.
7371
pub(crate) fn reset(&mut self, k: usize) {
7472
self.first = true;
75-
self.done = false;
7673

7774
if k < self.indices.len() {
7875
self.indices.truncate(k);
@@ -93,30 +90,32 @@ impl<I: Iterator> Combinations<I> {
9390
indices,
9491
pool,
9592
first,
96-
done: _,
9793
} = self;
9894
let n = pool.count();
9995
(n, remaining_for(n, first, &indices).unwrap())
10096
}
10197

10298
/// Initialises the iterator by filling a buffer with elements from the
103-
/// iterator.
104-
fn init(&mut self) {
99+
/// iterator, return a boolean indicating whether or not we've run out of
100+
/// combinations.
101+
fn init(&mut self) -> bool {
105102
self.pool.prefill(self.k());
106-
if self.k() > self.n() {
107-
self.done = true;
108-
} else {
103+
let done = self.k() > self.n();
104+
if !done {
109105
self.first = false;
110106
}
107+
108+
done
111109
}
112110

113111
/// Increments indices representing the combination to advance to the next
114112
/// (in lexicographic order by increasing sequence) combination. For example
115113
/// if we have n=3 & k=2 then [0, 1] -> [0, 2] -> [0, 3] -> [1, 2] -> ...
116-
fn increment_indices(&mut self) {
114+
///
115+
/// Returns a boolean indicating whether or not we've run out of combinations.
116+
fn increment_indices(&mut self) -> bool {
117117
if self.indices.is_empty() {
118-
self.done = true;
119-
return;
118+
return true; // Done
120119
}
121120

122121
// Scan from the end, looking for an index to increment
@@ -132,8 +131,7 @@ impl<I: Iterator> Combinations<I> {
132131
i -= 1;
133132
} else {
134133
// Reached the last combination
135-
self.done = true;
136-
return;
134+
return true;
137135
}
138136
}
139137

@@ -142,6 +140,9 @@ impl<I: Iterator> Combinations<I> {
142140
for j in i + 1..self.indices.len() {
143141
self.indices[j] = self.indices[j - 1] + 1;
144142
}
143+
144+
// If we've made it this far, we haven't run out of combos
145+
false
145146
}
146147
}
147148

@@ -152,30 +153,37 @@ where
152153
{
153154
type Item = Vec<I::Item>;
154155
fn next(&mut self) -> Option<Self::Item> {
155-
if self.first {
156+
let done = if self.first {
156157
self.init()
157158
} else {
158159
self.increment_indices()
159-
}
160+
};
160161

161-
if self.done {
162+
if done {
162163
return None;
163164
}
164165

165166
Some(self.indices.iter().map(|i| self.pool[*i].clone()).collect())
166167
}
167168

168169
fn nth(&mut self, n: usize) -> Option<Self::Item> {
169-
// Delegate initialisation work to next()
170-
let first = self.next();
171-
172170
if n == 0 {
173-
return first;
171+
return self.next();
172+
}
173+
174+
let mut done = if self.first {
175+
self.init()
176+
} else {
177+
self.increment_indices()
178+
};
179+
180+
if done {
181+
return None;
174182
}
175183

176184
for _ in 0..(n - 1) {
177-
self.increment_indices();
178-
if self.done {
185+
done = self.increment_indices();
186+
if done {
179187
return None;
180188
}
181189
}

0 commit comments

Comments
 (0)