3 use super::lazy_buffer
::LazyBuffer
;
5 /// An iterator to iterate through all the `n`-length combinations in an iterator, with replacement.
7 /// See [`.combinations_with_replacement()`](../trait.Itertools.html#method.combinations_with_replacement) for more information.
9 pub struct CombinationsWithReplacement
<I
>
16 // The current known max index value. This increases as pool grows.
22 impl<I
> fmt
::Debug
for CombinationsWithReplacement
<I
>
24 I
: Iterator
+ fmt
::Debug
,
25 I
::Item
: fmt
::Debug
+ Clone
,
27 debug_fmt_fields
!(Combinations
, k
, indices
, max_index
, pool
, first
);
30 impl<I
> CombinationsWithReplacement
<I
>
35 /// Map the current mask over the pool to get an output combination
36 fn current(&self) -> Vec
<I
::Item
> {
37 self.indices
.iter().map(|i
| self.pool
[*i
].clone()).collect()
41 /// Create a new `CombinationsWithReplacement` from a clonable iterator.
42 pub fn combinations_with_replacement
<I
>(iter
: I
, k
: usize) -> CombinationsWithReplacement
<I
>
47 let indices
: Vec
<usize> = vec
![0; k
];
48 let pool
: LazyBuffer
<I
> = LazyBuffer
::new(iter
);
50 CombinationsWithReplacement
{
59 impl<I
> Iterator
for CombinationsWithReplacement
<I
>
64 type Item
= Vec
<I
::Item
>;
65 fn next(&mut self) -> Option
<Self::Item
> {
66 // If this is the first iteration, return early
68 // In empty edge cases, stop iterating immediately
69 return if self.k
== 0 || self.pool
.is_done() {
71 // Otherwise, yield the initial state
78 // Check if we need to consume more from the iterator
79 // This will run while we increment our first index digit
80 if !self.pool
.is_done() {
82 self.max_index
= self.pool
.len() - 1;
85 // Work out where we need to update our indices
86 let mut increment
: Option
<(usize, usize)> = None
;
87 for (i
, indices_int
) in self.indices
.iter().enumerate().rev() {
88 if indices_int
< &self.max_index
{
89 increment
= Some((i
, indices_int
+ 1));
95 // If we can update the indices further
96 Some((increment_from
, increment_value
)) => {
97 // We need to update the rightmost non-max value
98 // and all those to the right
99 for indices_index
in increment_from
..self.indices
.len() {
100 self.indices
[indices_index
] = increment_value
104 // Otherwise, we're done