malachite_base/iterators/
mod.rs

1// Copyright © 2025 Mikhail Hogrefe
2//
3// This file is part of Malachite.
4//
5// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
6// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
7// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
8
9#[cfg(feature = "random")]
10use crate::bools::random::{WeightedRandomBools, weighted_random_bools};
11use crate::num::arithmetic::traits::Parity;
12use crate::num::basic::traits::Zero;
13#[cfg(feature = "random")]
14use crate::random::Seed;
15#[cfg(feature = "random")]
16use crate::vecs::{RandomValuesFromVec, random_values_from_vec};
17use alloc::collections::VecDeque;
18use alloc::string::{String, ToString};
19use alloc::vec::Vec;
20use core::fmt::Display;
21use core::hash::Hash;
22use hashbrown::HashSet;
23use itertools::Itertools;
24
25/// Generates all the nonzero values of a provided iterator.
26///
27/// This `struct` is created by [`nonzero_values`]; see its documentation for more.
28#[derive(Clone, Debug)]
29pub struct NonzeroValues<I: Iterator>(I)
30where
31    I::Item: PartialEq<I::Item> + Zero;
32
33impl<I: Iterator> Iterator for NonzeroValues<I>
34where
35    I::Item: PartialEq<I::Item> + Zero,
36{
37    type Item = I::Item;
38
39    #[inline]
40    fn next(&mut self) -> Option<I::Item> {
41        loop {
42            let x = self.0.next();
43            if x != Some(I::Item::ZERO) {
44                return x;
45            }
46        }
47    }
48}
49
50impl<I: DoubleEndedIterator> DoubleEndedIterator for NonzeroValues<I>
51where
52    I::Item: PartialEq<I::Item> + Zero,
53{
54    #[inline]
55    fn next_back(&mut self) -> Option<I::Item> {
56        loop {
57            let x = self.0.next_back();
58            if x != Some(I::Item::ZERO) {
59                return x;
60            }
61        }
62    }
63}
64
65/// Returns an iterator that generates all the nonzero values of a provided iterator.
66///
67/// `nonzero_values(xs)` generates the same values as `xs.filter(|x| x != I::Item::ZERO)`, but its
68/// type is easier to work with.
69///
70/// This iterator will hang if given an iterator that produces an infinite suffix of zeros.
71///
72/// The output length is the number of nonzero values produced by `xs`.
73///
74/// # Examples
75/// ```
76/// use itertools::Itertools;
77/// use malachite_base::iterators::nonzero_values;
78///
79/// assert_eq!(
80///     nonzero_values([-3i8, -2, -1, 0, 1, 2, 3].iter().cloned()).collect_vec(),
81///     &[-3, -2, -1, 1, 2, 3]
82/// )
83/// ```
84#[inline]
85pub const fn nonzero_values<I: Iterator>(xs: I) -> NonzeroValues<I>
86where
87    I::Item: PartialEq<I::Item> + Zero,
88{
89    NonzeroValues(xs)
90}
91
92/// Returns whether all of the values generated by an iterator are equal.
93///
94/// `is_constant(xs)` is equivalent to `xs.unique().count() == 1` for finite nonempty iterators, but
95/// is more efficient, doesn't require [`Clone`] or [`Hash`] implementations, and doesn't hang if
96/// provided an infinite non-constant iterator.
97///
98/// This function will hang if given an infinite constant iterator.
99///
100/// # Examples
101/// ```
102/// use malachite_base::iterators::is_constant;
103///
104/// assert_eq!(is_constant([1; 4].iter()), true);
105/// assert_eq!(is_constant([1, 2, 3, 4].iter()), false);
106/// assert_eq!(is_constant(0..), false);
107/// ```
108pub fn is_constant<I: Iterator>(xs: I) -> bool
109where
110    I::Item: Eq,
111{
112    let mut first = None;
113    for x in xs {
114        if let Some(ref first) = first {
115            if x != *first {
116                return false;
117            }
118        } else {
119            first = Some(x);
120        }
121    }
122    true
123}
124
125/// Returns whether an iterator returns at least some number of values.
126///
127/// `count_is_at_least(xs, n)` is equivalent to `xs.count() >= n` for finite iterators, but doesn't
128/// hang if provided an infinite iterator.
129///
130/// # Examples
131/// ```
132/// use malachite_base::iterators::count_is_at_least;
133///
134/// assert_eq!(count_is_at_least([1, 2, 3, 4].iter(), 3), true);
135/// assert_eq!(count_is_at_least([1, 2, 3, 4].iter(), 4), true);
136/// assert_eq!(count_is_at_least([1, 2, 3, 4].iter(), 5), false);
137/// assert_eq!(count_is_at_least(0.., 5), true);
138/// ```
139#[inline]
140pub fn count_is_at_least<I: Iterator>(xs: I, n: usize) -> bool {
141    xs.take(n).count() == n
142}
143
144/// Returns whether an iterator returns at most some number of values.
145///
146/// `count_is_at_most(xs, n)` is equivalent to `xs.count() <= n` for finite iterators, but doesn't
147/// hang if provided an infinite iterator.
148///
149/// # Examples
150/// ```
151/// use malachite_base::iterators::count_is_at_most;
152///
153/// assert_eq!(count_is_at_most([1, 2, 3, 4].iter(), 3), false);
154/// assert_eq!(count_is_at_most([1, 2, 3, 4].iter(), 4), true);
155/// assert_eq!(count_is_at_most([1, 2, 3, 4].iter(), 5), true);
156/// assert_eq!(count_is_at_most(0.., 5), false);
157/// ```
158#[inline]
159pub fn count_is_at_most<I: Iterator>(xs: I, n: usize) -> bool {
160    xs.take(n + 1).count() <= n
161}
162
163/// Returns whether an iterator never returns the same value twice.
164///
165/// `is_unique(xs)` is equivalent to `xs.unique().count() <= 1` for finite iterators, but is more
166/// efficient and doesn't hang if provided a non-unique infinite iterator.
167///
168/// This iterator will hang if given an infinite unique iterator.
169///
170/// # Examples
171/// ```
172/// use malachite_base::iterators::is_unique;
173///
174/// let empty: [u32; 0] = [];
175/// assert_eq!(is_unique(empty.iter()), true);
176/// assert_eq!(is_unique([1, 2, 3, 4].iter()), true);
177/// assert_eq!(is_unique([1, 2, 3, 1].iter()), false);
178/// assert_eq!(is_unique((0..).map(|i| i / 2)), false);
179/// ```
180#[inline]
181pub fn is_unique<I: Iterator>(xs: I) -> bool
182where
183    I::Item: Eq + Hash,
184{
185    let mut set = HashSet::new();
186    for x in xs {
187        if !set.insert(x) {
188            return false;
189        }
190    }
191    true
192}
193
194/// Returns the first and last elements of an iterator, or `None` if it is empty.
195///
196/// The iterator's elements must be cloneable, since if the iterator consists of a single element
197/// `x`, the result will be `(x, x)`.
198///
199/// This iterator will hang if given an infinite iterator.
200///
201/// # Examples
202/// ```
203/// use malachite_base::iterators::first_and_last;
204///
205/// let empty: [u32; 0] = [];
206/// assert_eq!(first_and_last(&mut empty.iter()), None);
207/// assert_eq!(first_and_last(&mut [1].iter().cloned()), Some((1, 1)));
208/// assert_eq!(first_and_last(&mut [1, 2, 3].iter().cloned()), Some((1, 3)));
209/// ```
210pub fn first_and_last<I: Iterator>(xs: &mut I) -> Option<(I::Item, I::Item)>
211where
212    I::Item: Clone,
213{
214    xs.next().map(|first| {
215        if let Some(last) = xs.last() {
216            (first, last)
217        } else {
218            (first.clone(), first)
219        }
220    })
221}
222
223/// Groups elements of an iterator into intervals of adjacent elements that match a predicate. The
224/// endpoints of each interval are returned.
225///
226/// The intervals are inclusive.
227///
228/// This iterator will hang if given an infinite iterator.
229///
230/// # Examples
231/// ```
232/// use malachite_base::iterators::matching_intervals_in_iterator;
233///
234/// let xs = &[1, 2, 10, 11, 12, 7, 8, 16, 5];
235/// assert_eq!(
236///     matching_intervals_in_iterator(xs.iter().cloned(), |&x| x >= 10).as_slice(),
237///     &[(10, 12), (16, 16)]
238/// );
239/// assert_eq!(
240///     matching_intervals_in_iterator(xs.iter().cloned(), |&x| x < 10).as_slice(),
241///     &[(1, 2), (7, 8), (5, 5)]
242/// );
243/// ```
244pub fn matching_intervals_in_iterator<I: Iterator, F: Fn(&I::Item) -> bool>(
245    xs: I,
246    predicate: F,
247) -> Vec<(I::Item, I::Item)>
248where
249    I::Item: Clone,
250{
251    xs.group_by(predicate)
252        .into_iter()
253        .filter_map(|(b, mut group)| if b { first_and_last(&mut group) } else { None })
254        .collect()
255}
256
257#[cfg(feature = "random")]
258/// An iterator that randomly produces another iterator's values, or produces a special value.
259///
260/// This `struct` is created by [`with_special_value`]; see its documentation for more.
261#[derive(Clone, Debug)]
262pub struct WithSpecialValue<I: Iterator>
263where
264    I::Item: Clone,
265{
266    bs: WeightedRandomBools,
267    special_value: I::Item,
268    xs: I,
269}
270
271#[cfg(feature = "random")]
272impl<I: Iterator> Iterator for WithSpecialValue<I>
273where
274    I::Item: Clone,
275{
276    type Item = I::Item;
277
278    fn next(&mut self) -> Option<I::Item> {
279        if self.bs.next().unwrap() {
280            Some(self.special_value.clone())
281        } else {
282            self.xs.next()
283        }
284    }
285}
286
287#[cfg(feature = "random")]
288/// An iterator that randomly produces another iterator's values, or produces a special value.
289///
290/// Let $n_p$ be `p_numerator`, $d_p$ be `p_denominator`, and let $p=n_p/d_p$.
291///
292/// Every time a value is to be generated, the iterator returns the special value with probability
293/// $p$, or else returns a value from the inner iterator.
294///
295/// If $p > 0$, the output length is infinite. Otherwise, it is the same as the length of `xs`.
296///
297/// # Panics
298/// Panics if `p_denominator` is 0 or `p_numerator` is greater than `p_denominator`.
299///
300/// # Examples
301/// ```
302/// use malachite_base::iterators::{prefix_to_string, with_special_value};
303/// use malachite_base::num::random::random_primitive_ints;
304/// use malachite_base::random::EXAMPLE_SEED;
305///
306/// assert_eq!(
307///     prefix_to_string(
308///         with_special_value(EXAMPLE_SEED, -1i16, 1, 2, &random_primitive_ints::<i16>),
309///         20
310///     ),
311///     "[-1, -1, -1, 2901, -1, -14200, -1, -1, -1, -30997, -8245, -5338, -1, -1, -20007, -1, -1, \
312///     -1, -1, -1, ...]"
313/// );
314/// ```
315pub fn with_special_value<I: Iterator>(
316    seed: Seed,
317    special_value: I::Item,
318    p_numerator: u64,
319    p_denominator: u64,
320    xs_gen: &dyn Fn(Seed) -> I,
321) -> WithSpecialValue<I>
322where
323    I::Item: Clone,
324{
325    WithSpecialValue {
326        bs: weighted_random_bools(seed.fork("bs"), p_numerator, p_denominator),
327        special_value,
328        xs: xs_gen(seed.fork("xs")),
329    }
330}
331
332#[cfg(feature = "random")]
333/// An iterator that randomly produces another iterator's values, or samples from a [`Vec`] of
334/// special values.
335///
336/// This `struct` is created by [`with_special_values`]; see its documentation for more.
337#[derive(Clone, Debug)]
338pub struct WithSpecialValues<I: Iterator>
339where
340    I::Item: Clone,
341{
342    bs: WeightedRandomBools,
343    special_values: RandomValuesFromVec<I::Item>,
344    xs: I,
345}
346
347#[cfg(feature = "random")]
348impl<I: Iterator> Iterator for WithSpecialValues<I>
349where
350    I::Item: Clone,
351{
352    type Item = I::Item;
353
354    fn next(&mut self) -> Option<I::Item> {
355        if self.bs.next().unwrap() {
356            self.special_values.next()
357        } else {
358            self.xs.next()
359        }
360    }
361}
362
363#[cfg(feature = "random")]
364/// An iterator that randomly produces another iterator's values, or produces a random special value
365/// from a [`Vec`].
366///
367/// Let $n_p$ be `p_numerator`, $d_p$ be `p_denominator`, and let $p=n_p/d_p$.
368///
369/// Every time a value is to be generated, the iterator uniformly samples the special values [`Vec`]
370/// with probability $p$, or else returns a value from the inner iterator.
371///
372/// If $p > 0$, the output length is infinite. Otherwise, it is the same as the length of `xs`.
373///
374/// # Worst-case complexity per iteration
375/// Constant time and additional memory.
376///
377/// # Panics
378/// Panics if `special_values` is empty, `p_denominator` is 0, or if `p_numerator` is greater than
379/// `p_denominator`.
380///
381/// # Examples
382/// ```
383/// use malachite_base::iterators::{prefix_to_string, with_special_values};
384/// use malachite_base::num::random::random_primitive_ints;
385/// use malachite_base::random::EXAMPLE_SEED;
386///
387/// assert_eq!(
388///     prefix_to_string(
389///         with_special_values(
390///             EXAMPLE_SEED,
391///             vec![1, 2, 3],
392///             1,
393///             2,
394///             &random_primitive_ints::<i16>
395///         ),
396///         20,
397///     ),
398///     "[3, 1, 3, 2901, 1, -14200, 2, 3, 1, -30997, -8245, -5338, 1, 1, -20007, 3, 1, 1, 1, 1, \
399///     ...]"
400/// );
401/// ```
402pub fn with_special_values<I: Iterator>(
403    seed: Seed,
404    special_values: Vec<I::Item>,
405    p_numerator: u64,
406    p_denominator: u64,
407    xs_gen: &dyn Fn(Seed) -> I,
408) -> WithSpecialValues<I>
409where
410    I::Item: Clone,
411{
412    WithSpecialValues {
413        bs: weighted_random_bools(seed.fork("bs"), p_numerator, p_denominator),
414        special_values: random_values_from_vec(seed.fork("special_values"), special_values),
415        xs: xs_gen(seed.fork("xs")),
416    }
417}
418
419/// Generates sliding windows of elements from an iterator.
420///
421/// This `struct` is created by [`iter_windows`]; see its documentation for more.
422#[derive(Clone, Debug)]
423pub struct IterWindows<I: Iterator>
424where
425    I::Item: Clone,
426{
427    xs: I,
428    window: VecDeque<I::Item>,
429    window_size: usize,
430}
431
432impl<I: Iterator> Iterator for IterWindows<I>
433where
434    I::Item: Clone,
435{
436    type Item = VecDeque<I::Item>;
437
438    fn next(&mut self) -> Option<VecDeque<I::Item>> {
439        if self.window.len() < self.window_size {
440            self.window = (&mut self.xs).take(self.window_size).collect();
441            if self.window.len() < self.window_size {
442                None
443            } else {
444                Some(self.window.clone())
445            }
446        } else {
447            let x = self.xs.next()?;
448            self.window.pop_front();
449            self.window.push_back(x);
450            Some(self.window.clone())
451        }
452    }
453}
454
455/// Returns windows of $n$ adjacent elements of an iterator, advancing the window by 1 in each
456/// iteration. The values are cloned each time a new window is generated.
457///
458/// The output length is $n - k + 1$, where $n$ is `xs.count()` and $k$ is `window_size`.
459///
460/// # Panics
461/// Panics if `window_size` is 0.
462///
463/// # Examples
464/// ```
465/// use itertools::Itertools;
466/// use malachite_base::iterators::iter_windows;
467///
468/// let xs = 0..=5;
469/// let windows = iter_windows(3, xs)
470///     .map(|ws| ws.iter().cloned().collect_vec())
471///     .collect_vec();
472/// assert_eq!(
473///     windows.iter().map(Vec::as_slice).collect_vec().as_slice(),
474///     &[&[0, 1, 2], &[1, 2, 3], &[2, 3, 4], &[3, 4, 5]]
475/// );
476/// ```
477pub fn iter_windows<I: Iterator>(window_size: usize, xs: I) -> IterWindows<I>
478where
479    I::Item: Clone,
480{
481    assert_ne!(window_size, 0);
482    IterWindows {
483        xs,
484        window: VecDeque::with_capacity(window_size),
485        window_size,
486    }
487}
488
489/// Converts a prefix of an iterator to a string.
490///
491/// Suppose the iterator generates $(a, b, c, d)$. If `max_len` is 3, this function will return the
492/// string `"[a, b, c, ...]"`. If `max_len` is 4 or more, this function will return `[a, b, c, d]`.
493///
494/// This function will attempt to advance the iterator `max_len + 1` times. The extra time is used
495/// determine whether the output string should contain an ellipsis.
496///
497/// # Panics
498/// Panics if `max_len` is 0.
499///
500/// # Examples
501/// ```
502/// use malachite_base::iterators::prefix_to_string;
503///
504/// assert_eq!(prefix_to_string(0..10, 3), "[0, 1, 2, ...]");
505/// assert_eq!(prefix_to_string(0..4, 5), "[0, 1, 2, 3]");
506/// ```
507pub fn prefix_to_string<I: Iterator>(mut xs: I, max_len: usize) -> String
508where
509    I::Item: Display,
510{
511    assert_ne!(max_len, 0);
512    let mut s = String::new();
513    s.push('[');
514    let mut first = true;
515    let mut done = false;
516    for _ in 0..max_len {
517        if let Some(x) = xs.next() {
518            if first {
519                first = false;
520            } else {
521                s.push_str(", ");
522            }
523            s.push_str(&x.to_string());
524        } else {
525            done = true;
526            break;
527        }
528    }
529    if !done && xs.next().is_some() {
530        s.push_str(", ...");
531    }
532    s.push(']');
533    s
534}
535
536/// An iterator that generates the Thue-Morse sequence. See [`thue_morse_sequence`] for more
537/// information.
538#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
539pub struct ThueMorseSequence(u64);
540
541impl Iterator for ThueMorseSequence {
542    type Item = bool;
543
544    fn next(&mut self) -> Option<bool> {
545        let b = self.0.count_ones().odd();
546        self.0 += 1;
547        Some(b)
548    }
549}
550
551/// Returns an iterator that generates the Thue-Morse sequence.
552///
553/// The output length is infinite.
554///
555/// # Worst-case complexity per iteration
556/// Constant time and additional memory.
557///
558/// # Examples
559/// ```
560/// use malachite_base::iterators::thue_morse_sequence;
561///
562/// let s: String = thue_morse_sequence()
563///     .take(100)
564///     .map(|b| if b { '1' } else { '0' })
565///     .collect();
566/// assert_eq!(
567///     s,
568///     "01101001100101101001011001101001100101100110100101101001100101101001011001101001011010011\
569///     00101100110"
570/// )
571/// ```
572#[inline]
573pub const fn thue_morse_sequence() -> ThueMorseSequence {
574    ThueMorseSequence(0)
575}
576
577/// Contains [`BitDistributor`](bit_distributor::BitDistributor), which helps generate tuples
578/// exhaustively.
579pub mod bit_distributor;
580/// Functions that compare adjacent iterator elements.
581pub mod comparison;
582/// Contains [`IteratorCache`](iterator_cache::IteratorCache), which remembers values produced by an
583/// iterator.
584pub mod iterator_cache;