From 9918693037dce8aa4bb6f08741b6812923486c18 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 19 Jun 2024 11:26:03 +0200 Subject: Merging upstream version 1.76.0+dfsg1. Signed-off-by: Daniel Baumann --- .../src/combinations_with_replacement.rs | 109 +++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 vendor/itertools-0.11.0/src/combinations_with_replacement.rs (limited to 'vendor/itertools-0.11.0/src/combinations_with_replacement.rs') diff --git a/vendor/itertools-0.11.0/src/combinations_with_replacement.rs b/vendor/itertools-0.11.0/src/combinations_with_replacement.rs new file mode 100644 index 000000000..0fec9671a --- /dev/null +++ b/vendor/itertools-0.11.0/src/combinations_with_replacement.rs @@ -0,0 +1,109 @@ +use alloc::vec::Vec; +use std::fmt; +use std::iter::FusedIterator; + +use super::lazy_buffer::LazyBuffer; + +/// An iterator to iterate through all the `n`-length combinations in an iterator, with replacement. +/// +/// See [`.combinations_with_replacement()`](crate::Itertools::combinations_with_replacement) +/// for more information. +#[derive(Clone)] +pub struct CombinationsWithReplacement +where + I: Iterator, + I::Item: Clone, +{ + indices: Vec, + pool: LazyBuffer, + first: bool, +} + +impl fmt::Debug for CombinationsWithReplacement +where + I: Iterator + fmt::Debug, + I::Item: fmt::Debug + Clone, +{ + debug_fmt_fields!(Combinations, indices, pool, first); +} + +impl CombinationsWithReplacement +where + I: Iterator, + I::Item: Clone, +{ + /// Map the current mask over the pool to get an output combination + fn current(&self) -> Vec { + self.indices.iter().map(|i| self.pool[*i].clone()).collect() + } +} + +/// Create a new `CombinationsWithReplacement` from a clonable iterator. +pub fn combinations_with_replacement(iter: I, k: usize) -> CombinationsWithReplacement +where + I: Iterator, + I::Item: Clone, +{ + let indices: Vec = alloc::vec![0; k]; + let pool: LazyBuffer = LazyBuffer::new(iter); + + CombinationsWithReplacement { + indices, + pool, + first: true, + } +} + +impl Iterator for CombinationsWithReplacement +where + I: Iterator, + I::Item: Clone, +{ + type Item = Vec; + fn next(&mut self) -> Option { + // If this is the first iteration, return early + if self.first { + // In empty edge cases, stop iterating immediately + return if !(self.indices.is_empty() || self.pool.get_next()) { + None + // Otherwise, yield the initial state + } else { + self.first = false; + Some(self.current()) + }; + } + + // Check if we need to consume more from the iterator + // This will run while we increment our first index digit + self.pool.get_next(); + + // Work out where we need to update our indices + let mut increment: Option<(usize, usize)> = None; + for (i, indices_int) in self.indices.iter().enumerate().rev() { + if *indices_int < self.pool.len()-1 { + increment = Some((i, indices_int + 1)); + break; + } + } + + match increment { + // If we can update the indices further + Some((increment_from, increment_value)) => { + // We need to update the rightmost non-max value + // and all those to the right + for indices_index in increment_from..self.indices.len() { + self.indices[indices_index] = increment_value; + } + Some(self.current()) + } + // Otherwise, we're done + None => None, + } + } +} + +impl FusedIterator for CombinationsWithReplacement +where + I: Iterator, + I::Item: Clone, +{} -- cgit v1.2.3