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;