Skip to main content

malachite_base/tuples/
mod.rs

1// Copyright © 2026 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/// Generates all singletons (1-element tuples) with values from a given iterator.
10///
11/// This `struct` is created by [`singletons`]; see its documentation for more.
12#[derive(Clone, Debug, Eq, PartialEq)]
13pub struct Singletons<I: Iterator> {
14    xs: I,
15}
16
17impl<I: Iterator> Iterator for Singletons<I> {
18    type Item = (I::Item,);
19
20    #[inline]
21    fn next(&mut self) -> Option<(I::Item,)> {
22        self.xs.next().map(|x| (x,))
23    }
24}
25
26/// Generates all singletons (1-element tuples) with values from a given iterator.
27///
28/// The elements appear in the same order as they do in the given iterator, but wrapped in `(_,)`.
29///
30/// The output length is `xs.count()`.
31///
32/// # Worst-case complexity per iteration
33/// $T(i) = O(T^\prime(i))$
34///
35/// $M(i) = O(M^\prime(i))$
36///
37/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, and $T^\prime$ and
38/// $M^\prime$ are the time and memory functions of `xs`.
39///
40/// # Examples
41/// ```
42/// use itertools::Itertools;
43/// use malachite_base::tuples::singletons;
44///
45/// assert_eq!(
46///     singletons([1, 2, 3].iter().cloned()).collect_vec(),
47///     &[(1,), (2,), (3,)]
48/// );
49/// ```
50#[inline]
51pub const fn singletons<I: Iterator>(xs: I) -> Singletons<I> {
52    Singletons { xs }
53}
54
55/// Iterators that generate tuples without repetition.
56///
57/// To reduce binary size and lower compilation time, many of the functions described here are not
58/// actually defined in Malachite, but may be created in your program using macros exported from
59/// Malachite. To do this, see the documentation for `lex_tuples` and `lex_custom_tuples`.
60///
61/// # lex_pairs
62/// ```
63/// use itertools::Itertools;
64/// use malachite_base::tuples::exhaustive::lex_pairs;
65///
66/// assert_eq!(
67///     lex_pairs('a'..'f', 0..3).collect_vec(),
68///     &[
69///         ('a', 0),
70///         ('a', 1),
71///         ('a', 2),
72///         ('b', 0),
73///         ('b', 1),
74///         ('b', 2),
75///         ('c', 0),
76///         ('c', 1),
77///         ('c', 2),
78///         ('d', 0),
79///         ('d', 1),
80///         ('d', 2),
81///         ('e', 0),
82///         ('e', 1),
83///         ('e', 2)
84///     ]
85/// );
86/// ```
87///
88/// # lex_pairs_from_single
89/// ```
90/// use itertools::Itertools;
91/// use malachite_base::tuples::exhaustive::lex_pairs_from_single;
92///
93/// assert_eq!(
94///     lex_pairs_from_single(0..3).collect_vec(),
95///     &[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
96/// );
97/// ```
98///
99/// # lex_triples_xyx
100/// ```
101/// use itertools::Itertools;
102/// use malachite_base::iterators::iterator_cache::IteratorCache;
103/// use malachite_base::lex_custom_tuples;
104///
105/// fn unwrap_triple<X, Y, Z>((a, b, c): (Option<X>, Option<Y>, Option<Z>)) -> (X, Y, Z) {
106///     (a.unwrap(), b.unwrap(), c.unwrap())
107/// }
108///
109/// lex_custom_tuples!(
110///     (pub(crate)),
111///     LexTriplesXYX,
112///     (X, Y, X),
113///     (None, None, None),
114///     unwrap_triple,
115///     lex_triples_xyx,
116///     [X, I, xs, [0, x_0], [2, x_2]],
117///     [Y, J, ys, [1, y_1]]
118/// );
119///
120/// // We are generating triples of `char`, `i8`, and `char` using two input iterators. The first
121/// // iterator, `xs`, the chars 'a' through 'c', and the second, `ys`, produces the three numbers
122/// // 0, 1, and 2. The function we're using is `lex_triples_xyx`, meaning that the first element of
123/// // the output triples will be taken from `xs`, the second element from `ys`, and the third also
124/// // from `xs`.
125/// let ts = lex_triples_xyx('a'..='c', 0..3);
126/// assert_eq!(
127///     ts.collect_vec(),
128///     &[
129///         ('a', 0, 'a'),
130///         ('a', 0, 'b'),
131///         ('a', 0, 'c'),
132///         ('a', 1, 'a'),
133///         ('a', 1, 'b'),
134///         ('a', 1, 'c'),
135///         ('a', 2, 'a'),
136///         ('a', 2, 'b'),
137///         ('a', 2, 'c'),
138///         ('b', 0, 'a'),
139///         ('b', 0, 'b'),
140///         ('b', 0, 'c'),
141///         ('b', 1, 'a'),
142///         ('b', 1, 'b'),
143///         ('b', 1, 'c'),
144///         ('b', 2, 'a'),
145///         ('b', 2, 'b'),
146///         ('b', 2, 'c'),
147///         ('c', 0, 'a'),
148///         ('c', 0, 'b'),
149///         ('c', 0, 'c'),
150///         ('c', 1, 'a'),
151///         ('c', 1, 'b'),
152///         ('c', 1, 'c'),
153///         ('c', 2, 'a'),
154///         ('c', 2, 'b'),
155///         ('c', 2, 'c')
156///     ]
157/// );
158/// ```
159///
160/// # exhaustive_pairs_from_single
161/// ```
162/// use itertools::Itertools;
163/// use malachite_base::tuples::exhaustive::exhaustive_pairs_from_single;
164///
165/// assert_eq!(
166///     exhaustive_pairs_from_single(0..4).collect_vec(),
167///     &[
168///         (0, 0),
169///         (0, 1),
170///         (1, 0),
171///         (1, 1),
172///         (0, 2),
173///         (0, 3),
174///         (1, 2),
175///         (1, 3),
176///         (2, 0),
177///         (2, 1),
178///         (3, 0),
179///         (3, 1),
180///         (2, 2),
181///         (2, 3),
182///         (3, 2),
183///         (3, 3)
184///     ]
185/// );
186/// ```
187///
188/// # exhaustive_pairs_1_input
189/// ```
190/// use itertools::Itertools;
191/// use malachite_base::chars::exhaustive::exhaustive_ascii_chars;
192/// use malachite_base::exhaustive_tuples_1_input;
193/// use malachite_base::iterators::bit_distributor::{BitDistributor, BitDistributorOutputType};
194/// use malachite_base::iterators::iterator_cache::IteratorCache;
195/// use malachite_base::num::arithmetic::traits::CheckedPow;
196/// use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom};
197/// use malachite_base::num::logic::traits::SignificantBits;
198/// use std::cmp::max;
199/// use std::marker::PhantomData;
200///
201/// exhaustive_tuples_1_input!(
202///     (pub(crate)),
203///     ExhaustiveTriples1Input,
204///     exhaustive_triples_1_input,
205///     exhaustive_triples_from_single,
206///     (I::Item, I::Item, I::Item),
207///     [0, output_type_x],
208///     [1, output_type_y],
209///     [2, output_type_z]
210/// );
211///
212/// // We are generating triples of `char`s using one input iterator, which produces all ASCII
213/// // `char`s. The third element has a tiny output type, so it will grow more slowly than the other
214/// // two elements (though it doesn't look that way from the first few tuples).
215/// let ts = exhaustive_triples_1_input(
216///     exhaustive_ascii_chars(),
217///     BitDistributorOutputType::normal(1),
218///     BitDistributorOutputType::normal(1),
219///     BitDistributorOutputType::tiny(),
220/// );
221/// assert_eq!(
222///     ts.take(20).collect_vec(),
223///     &[
224///         ('a', 'a', 'a'),
225///         ('a', 'a', 'b'),
226///         ('a', 'a', 'c'),
227///         ('a', 'a', 'd'),
228///         ('a', 'b', 'a'),
229///         ('a', 'b', 'b'),
230///         ('a', 'b', 'c'),
231///         ('a', 'b', 'd'),
232///         ('a', 'a', 'e'),
233///         ('a', 'a', 'f'),
234///         ('a', 'a', 'g'),
235///         ('a', 'a', 'h'),
236///         ('a', 'b', 'e'),
237///         ('a', 'b', 'f'),
238///         ('a', 'b', 'g'),
239///         ('a', 'b', 'h'),
240///         ('b', 'a', 'a'),
241///         ('b', 'a', 'b'),
242///         ('b', 'a', 'c'),
243///         ('b', 'a', 'd')
244///     ]
245/// );
246/// ```
247///
248/// # exhaustive_pairs
249/// ```
250/// use itertools::Itertools;
251/// use malachite_base::tuples::exhaustive::exhaustive_pairs;
252///
253/// let xss = exhaustive_pairs(['a', 'b', 'c'].iter().cloned(), 0..3).collect_vec();
254/// assert_eq!(
255///     xss,
256///     &[('a', 0), ('a', 1), ('b', 0), ('b', 1), ('a', 2), ('b', 2), ('c', 0), ('c', 1), ('c', 2)]
257/// );
258/// ```
259///
260/// # exhaustive_pairs_custom_output
261/// ```
262/// use itertools::Itertools;
263/// use malachite_base::iterators::bit_distributor::BitDistributorOutputType;
264/// use malachite_base::tuples::exhaustive::exhaustive_pairs_custom_output;
265///
266/// let xss = exhaustive_pairs_custom_output(
267///     ['a', 'b', 'c'].iter().cloned(),
268///     0..3,
269///     BitDistributorOutputType::normal(1),
270///     BitDistributorOutputType::tiny(),
271/// )
272/// .collect_vec();
273/// assert_eq!(
274///     xss,
275///     &[('a', 0), ('a', 1), ('a', 2), ('b', 0), ('b', 1), ('b', 2), ('c', 0), ('c', 1), ('c', 2)]
276/// );
277/// ```
278///
279/// # exhaustive_triples_xyx
280/// ```
281/// use itertools::Itertools;
282/// use malachite_base::chars::exhaustive::exhaustive_ascii_chars;
283/// use malachite_base::custom_tuples;
284/// use malachite_base::iterators::bit_distributor::{BitDistributor, BitDistributorOutputType};
285/// use malachite_base::iterators::iterator_cache::IteratorCache;
286/// use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom};
287/// use malachite_base::num::logic::traits::SignificantBits;
288/// use std::cmp::max;
289///
290/// #[allow(clippy::missing_const_for_fn)]
291/// fn unwrap_triple<X, Y, Z>((a, b, c): (Option<X>, Option<Y>, Option<Z>)) -> (X, Y, Z) {
292///     (a.unwrap(), b.unwrap(), c.unwrap())
293/// }
294///
295/// custom_tuples!(
296///     (pub(crate)),
297///     ExhaustiveTriplesXYX,
298///     (X, Y, X),
299///     (None, None, None),
300///     unwrap_triple,
301///     exhaustive_triples_xyx,
302///     exhaustive_triples_xyx_custom_output,
303///     [X, I, xs, xs_done, [0, output_type_xs_0], [2, output_type_ys_1]],
304///     [Y, J, ys, ys_done, [1, output_type_xs_2]]
305/// );
306///
307/// // We are generating triples of `char`, `i8`, and `char` using two input iterators. The first
308/// // iterator, `xs`, produces all ASCII `char`s, and the second, `ys`, produces the three numbers
309/// // 0, 1, and 2. The function we're using is `exhaustive_triples_xyx`, meaning that the first
310/// // element of the output triples will be taken from `xs`, the second element from `ys`, and the
311/// // third also from `xs`.
312/// let ts = exhaustive_triples_xyx(exhaustive_ascii_chars(), 0..3);
313/// assert_eq!(
314///     ts.take(20).collect_vec(),
315///     &[
316///         ('a', 0, 'a'),
317///         ('a', 0, 'b'),
318///         ('a', 1, 'a'),
319///         ('a', 1, 'b'),
320///         ('b', 0, 'a'),
321///         ('b', 0, 'b'),
322///         ('b', 1, 'a'),
323///         ('b', 1, 'b'),
324///         ('a', 0, 'c'),
325///         ('a', 0, 'd'),
326///         ('a', 1, 'c'),
327///         ('a', 1, 'd'),
328///         ('b', 0, 'c'),
329///         ('b', 0, 'd'),
330///         ('b', 1, 'c'),
331///         ('b', 1, 'd'),
332///         ('a', 2, 'a'),
333///         ('a', 2, 'b'),
334///         ('b', 2, 'a'),
335///         ('b', 2, 'b')
336///     ]
337/// );
338/// ```
339///
340/// # exhaustive_triples_xyx_custom_output
341/// ```
342/// use itertools::Itertools;
343/// use malachite_base::chars::exhaustive::exhaustive_ascii_chars;
344/// use malachite_base::custom_tuples;
345/// use malachite_base::iterators::bit_distributor::{BitDistributor, BitDistributorOutputType};
346/// use malachite_base::iterators::iterator_cache::IteratorCache;
347/// use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom};
348/// use malachite_base::num::logic::traits::SignificantBits;
349/// use std::cmp::max;
350///
351/// #[allow(clippy::missing_const_for_fn)]
352/// fn unwrap_triple<X, Y, Z>((a, b, c): (Option<X>, Option<Y>, Option<Z>)) -> (X, Y, Z) {
353///     (a.unwrap(), b.unwrap(), c.unwrap())
354/// }
355///
356/// custom_tuples!(
357///     (pub(crate)),
358///     ExhaustiveTriplesXYX,
359///     (X, Y, X),
360///     (None, None, None),
361///     unwrap_triple,
362///     exhaustive_triples_xyx,
363///     exhaustive_triples_xyx_custom_output,
364///     [X, I, xs, xs_done, [0, output_type_xs_0], [2, output_type_ys_1]],
365///     [Y, J, ys, ys_done, [1, output_type_xs_2]]
366/// );
367///
368/// // We are generating triples of `char`, `i8`, and `char` using two input iterators. The first
369/// // iterator, `xs`, produces all ASCII `char`s, and the second, `ys`, produces the three numbers
370/// // 0, 1, and 2. The function we're using is `exhaustive_triples_xyx_custom_output`, meaning that
371/// // the first element of the output triples will be taken from `xs`, the second element from
372/// // `ys`, and the third also from `xs`.
373/// //
374/// // The third element has a tiny output type, so it will grow more slowly than the other two
375/// // elements (though it doesn't look that way from the first few tuples).
376/// let ts = exhaustive_triples_xyx_custom_output(
377///     exhaustive_ascii_chars(),
378///     0..3,
379///     BitDistributorOutputType::normal(1),
380///     BitDistributorOutputType::normal(1),
381///     BitDistributorOutputType::tiny(),
382/// );
383/// assert_eq!(
384///     ts.take(20).collect_vec(),
385///     &[
386///         ('a', 0, 'a'),
387///         ('a', 0, 'b'),
388///         ('a', 0, 'c'),
389///         ('a', 0, 'd'),
390///         ('a', 1, 'a'),
391///         ('a', 1, 'b'),
392///         ('a', 1, 'c'),
393///         ('a', 1, 'd'),
394///         ('a', 0, 'e'),
395///         ('a', 0, 'f'),
396///         ('a', 0, 'g'),
397///         ('a', 0, 'h'),
398///         ('a', 1, 'e'),
399///         ('a', 1, 'f'),
400///         ('a', 1, 'g'),
401///         ('a', 1, 'h'),
402///         ('b', 0, 'a'),
403///         ('b', 0, 'b'),
404///         ('b', 0, 'c'),
405///         ('b', 0, 'd')
406///     ]
407/// );
408/// ```
409///
410/// # lex_ordered_unique_quadruples
411/// ```
412/// use itertools::Itertools;
413/// use malachite_base::iterators::iterator_cache::IteratorCache;
414/// use malachite_base::lex_ordered_unique_tuples;
415/// use malachite_base::vecs::exhaustive::fixed_length_ordered_unique_indices_helper;
416/// use std::marker::PhantomData;
417///
418/// lex_ordered_unique_tuples!(
419///     (pub(crate)),
420///     LexOrderedUniqueQuadruples,
421///     4,
422///     (I::Item, I::Item, I::Item, I::Item),
423///     lex_ordered_unique_quadruples,
424///     [0, 1, 2, 3]
425/// );
426///
427/// let xss = lex_ordered_unique_quadruples(1..=6).collect_vec();
428/// assert_eq!(
429///     xss.into_iter().collect_vec().as_slice(),
430///     &[
431///         (1, 2, 3, 4),
432///         (1, 2, 3, 5),
433///         (1, 2, 3, 6),
434///         (1, 2, 4, 5),
435///         (1, 2, 4, 6),
436///         (1, 2, 5, 6),
437///         (1, 3, 4, 5),
438///         (1, 3, 4, 6),
439///         (1, 3, 5, 6),
440///         (1, 4, 5, 6),
441///         (2, 3, 4, 5),
442///         (2, 3, 4, 6),
443///         (2, 3, 5, 6),
444///         (2, 4, 5, 6),
445///         (3, 4, 5, 6)
446///     ]
447/// );
448/// ```
449///
450/// # exhaustive_ordered_unique_quadruples
451/// ```
452/// use itertools::Itertools;
453/// use malachite_base::exhaustive_ordered_unique_tuples;
454/// use malachite_base::iterators::iterator_cache::IteratorCache;
455/// use malachite_base::vecs::exhaustive::next_bit_pattern;
456///
457/// exhaustive_ordered_unique_tuples!(
458///     (pub(crate)),
459///     ExhaustiveOrderedUniqueQuadruples,
460///     4,
461///     (I::Item, I::Item, I::Item, I::Item),
462///     exhaustive_ordered_unique_quadruples,
463///     [0, 1, 2, 3]
464/// );
465///
466/// let xss = exhaustive_ordered_unique_quadruples(1..=6).collect_vec();
467/// assert_eq!(
468///     xss.into_iter().collect_vec().as_slice(),
469///     &[
470///         (1, 2, 3, 4),
471///         (1, 2, 3, 5),
472///         (1, 2, 4, 5),
473///         (1, 3, 4, 5),
474///         (2, 3, 4, 5),
475///         (1, 2, 3, 6),
476///         (1, 2, 4, 6),
477///         (1, 3, 4, 6),
478///         (2, 3, 4, 6),
479///         (1, 2, 5, 6),
480///         (1, 3, 5, 6),
481///         (2, 3, 5, 6),
482///         (1, 4, 5, 6),
483///         (2, 4, 5, 6),
484///         (3, 4, 5, 6)
485///     ]
486/// );
487/// ```
488///
489/// # lex_unique_quadruples
490/// ```
491/// use itertools::Itertools;
492/// use malachite_base::iterators::iterator_cache::IteratorCache;
493/// use malachite_base::lex_unique_tuples;
494/// use malachite_base::vecs::exhaustive::{UniqueIndices, unique_indices};
495///
496/// lex_unique_tuples!(
497///     (pub(crate)),
498///     LexUniqueQuadruples,
499///     4,
500///     (I::Item, I::Item, I::Item, I::Item),
501///     lex_unique_quadruples,
502///     [0, 1, 2, 3]
503/// );
504///
505/// let xss = lex_unique_quadruples(1..=6).take(20).collect_vec();
506/// assert_eq!(
507///     xss.into_iter().collect_vec().as_slice(),
508///     &[
509///         (1, 2, 3, 4),
510///         (1, 2, 3, 5),
511///         (1, 2, 3, 6),
512///         (1, 2, 4, 3),
513///         (1, 2, 4, 5),
514///         (1, 2, 4, 6),
515///         (1, 2, 5, 3),
516///         (1, 2, 5, 4),
517///         (1, 2, 5, 6),
518///         (1, 2, 6, 3),
519///         (1, 2, 6, 4),
520///         (1, 2, 6, 5),
521///         (1, 3, 2, 4),
522///         (1, 3, 2, 5),
523///         (1, 3, 2, 6),
524///         (1, 3, 4, 2),
525///         (1, 3, 4, 5),
526///         (1, 3, 4, 6),
527///         (1, 3, 5, 2),
528///         (1, 3, 5, 4)
529///     ]
530/// );
531/// ```
532///
533/// # exhaustive_unique_quadruples
534/// ```
535/// use itertools::Itertools;
536/// use malachite_base::exhaustive_unique_tuples;
537/// use malachite_base::num::iterators::{RulerSequence, ruler_sequence};
538/// use malachite_base::tuples::exhaustive::{
539///     ExhaustiveDependentPairs, exhaustive_dependent_pairs,
540/// };
541/// use malachite_base::vecs::ExhaustiveVecPermutations;
542/// use malachite_base::vecs::exhaustive::{
543///     ExhaustiveOrderedUniqueCollections, ExhaustiveUniqueVecsGenerator,
544///     exhaustive_ordered_unique_vecs_fixed_length,
545/// };
546///
547/// exhaustive_unique_tuples!(
548///     (pub(crate)),
549///     ExhaustiveUniqueQuadruples,
550///     4,
551///     (I::Item, I::Item, I::Item, I::Item),
552///     exhaustive_unique_quadruples,
553///     [0, 1, 2, 3]
554/// );
555///
556/// let xss = exhaustive_unique_quadruples(1..=6).take(20).collect_vec();
557/// assert_eq!(
558///     xss.into_iter().collect_vec().as_slice(),
559///     &[
560///         (1, 2, 3, 4),
561///         (1, 2, 3, 5),
562///         (1, 2, 4, 3),
563///         (1, 2, 4, 5),
564///         (1, 3, 2, 4),
565///         (1, 2, 5, 3),
566///         (1, 3, 4, 2),
567///         (1, 3, 4, 5),
568///         (1, 4, 2, 3),
569///         (1, 3, 2, 5),
570///         (1, 4, 3, 2),
571///         (1, 2, 5, 4),
572///         (2, 1, 3, 4),
573///         (1, 3, 5, 2),
574///         (2, 1, 4, 3),
575///         (2, 3, 4, 5),
576///         (2, 3, 1, 4),
577///         (1, 5, 2, 3),
578///         (2, 3, 4, 1),
579///         (1, 4, 2, 5)
580///     ]
581/// );
582/// ```
583pub mod exhaustive;
584#[cfg(feature = "random")]
585/// Iterators that generate tuples randomly.
586///
587/// # random_pairs
588/// ```
589/// use itertools::Itertools;
590/// use malachite_base::chars::random::random_char_inclusive_range;
591/// use malachite_base::num::random::random_unsigned_inclusive_range;
592/// use malachite_base::random::EXAMPLE_SEED;
593/// use malachite_base::tuples::random::random_pairs;
594///
595/// let ps = random_pairs(
596///     EXAMPLE_SEED,
597///     &|seed| random_unsigned_inclusive_range::<u8>(seed, 0, 2),
598///     &|seed| random_char_inclusive_range(seed, 'x', 'z'),
599/// );
600/// assert_eq!(
601///     ps.take(20).collect_vec().as_slice(),
602///     &[
603///         (1, 'z'),
604///         (1, 'x'),
605///         (1, 'z'),
606///         (1, 'y'),
607///         (2, 'x'),
608///         (0, 'z'),
609///         (0, 'z'),
610///         (0, 'z'),
611///         (2, 'z'),
612///         (0, 'y'),
613///         (2, 'x'),
614///         (0, 'x'),
615///         (2, 'z'),
616///         (0, 'z'),
617///         (2, 'x'),
618///         (2, 'x'),
619///         (2, 'y'),
620///         (1, 'y'),
621///         (0, 'x'),
622///         (2, 'x')
623///     ]
624/// );
625/// ```
626///
627/// # random_pairs_from_single
628/// ```
629/// use itertools::Itertools;
630/// use malachite_base::num::random::random_unsigned_inclusive_range;
631/// use malachite_base::random::EXAMPLE_SEED;
632/// use malachite_base::tuples::random::random_pairs_from_single;
633///
634/// let ps = random_pairs_from_single(random_unsigned_inclusive_range::<u8>(EXAMPLE_SEED, 0, 2));
635/// assert_eq!(
636///     ps.take(20).collect_vec().as_slice(),
637///     &[
638///         (1, 0),
639///         (1, 2),
640///         (1, 1),
641///         (0, 1),
642///         (0, 2),
643///         (1, 0),
644///         (1, 2),
645///         (2, 0),
646///         (1, 0),
647///         (2, 2),
648///         (2, 1),
649///         (0, 2),
650///         (2, 1),
651///         (1, 1),
652///         (0, 0),
653///         (2, 0),
654///         (2, 2),
655///         (1, 0),
656///         (1, 1),
657///         (0, 2)
658///     ]
659/// );
660/// ```
661///
662/// # random_triples_xyx
663/// ```
664/// use itertools::Itertools;
665/// use malachite_base::chars::random::random_char_inclusive_range;
666/// use malachite_base::num::random::random_unsigned_inclusive_range;
667/// use malachite_base::random::{EXAMPLE_SEED, Seed};
668/// use malachite_base::random_custom_tuples;
669///
670/// random_custom_tuples!(
671///     (pub(crate)),
672///     RandomTriplesXYX,
673///     (X, Y, X),
674///     random_triples_xyx,
675///     [X, I, xs, xs_gen, [x_0, x_0], [x_2, y_1]],
676///     [Y, J, ys, ys_gen, [y_1, x_2]]
677/// );
678///
679/// // We are generating triples of `char`s using two input iterators. The first iterator, `xs`,
680/// // produces all ASCII `char`s, and the second, `ys`, produces the three numbers 0, 1, and 2. The
681/// // function we're using is `random_triples_xyx`, meaning that the first element of the
682/// // output triples will be taken from `xs`, the second element from `ys`, and the third also from
683/// // `xs`.
684/// let ts = random_triples_xyx(
685///     EXAMPLE_SEED,
686///     &|seed| random_char_inclusive_range(seed, 'x', 'z'),
687///     &|seed| random_unsigned_inclusive_range::<u8>(seed, 0, 2),
688/// );
689/// assert_eq!(
690///     ts.take(20).collect_vec().as_slice(),
691///     &[
692///         ('y', 2, 'y'),
693///         ('y', 0, 'y'),
694///         ('z', 2, 'x'),
695///         ('x', 1, 'x'),
696///         ('z', 0, 'x'),
697///         ('z', 2, 'x'),
698///         ('z', 2, 'x'),
699///         ('z', 2, 'z'),
700///         ('z', 2, 'y'),
701///         ('x', 1, 'z'),
702///         ('z', 0, 'x'),
703///         ('y', 0, 'z'),
704///         ('y', 2, 'z'),
705///         ('x', 2, 'z'),
706///         ('z', 0, 'y'),
707///         ('z', 0, 'y'),
708///         ('y', 1, 'x'),
709///         ('z', 1, 'z'),
710///         ('x', 0, 'z'),
711///         ('z', 0, 'x')
712///     ]
713/// );
714/// ```
715///
716/// # random_ordered_unique_quadruples
717/// ```
718/// use itertools::Itertools;
719/// use malachite_base::num::random::random_unsigned_inclusive_range;
720/// use malachite_base::random::EXAMPLE_SEED;
721/// use malachite_base::random_ordered_unique_tuples;
722/// use malachite_base::sets::random::{
723///     RandomBTreeSetsFixedLength, random_b_tree_sets_fixed_length,
724/// };
725///
726/// random_ordered_unique_tuples!(
727///     (pub(crate)),
728///     RandomOrderedUniqueQuadruples,
729///     4,
730///     (I::Item, I::Item, I::Item, I::Item),
731///     random_ordered_unique_quadruples,
732///     [0, 1, 2, 3]
733/// );
734///
735/// let qs = random_ordered_unique_quadruples(random_unsigned_inclusive_range::<u8>(
736///     EXAMPLE_SEED,
737///     1,
738///     10,
739/// ));
740/// assert_eq!(
741///     qs.take(20).collect_vec().as_slice(),
742///     &[
743///         (2, 5, 6, 8),
744///         (3, 5, 7, 9),
745///         (1, 2, 6, 8),
746///         (3, 4, 6, 7),
747///         (3, 6, 9, 10),
748///         (4, 6, 8, 10),
749///         (3, 6, 8, 10),
750///         (2, 5, 9, 10),
751///         (2, 3, 8, 10),
752///         (1, 3, 7, 8),
753///         (1, 2, 6, 10),
754///         (2, 5, 8, 9),
755///         (1, 8, 9, 10),
756///         (1, 3, 7, 8),
757///         (2, 3, 4, 5),
758///         (1, 3, 4, 8),
759///         (3, 6, 7, 9),
760///         (5, 6, 7, 8),
761///         (3, 4, 5, 9),
762///         (4, 6, 9, 10)
763///     ]
764/// );
765/// ```
766///
767/// # random_unique_quadruples
768/// ```
769/// use itertools::Itertools;
770/// use malachite_base::num::random::random_unsigned_inclusive_range;
771/// use malachite_base::random::EXAMPLE_SEED;
772/// use malachite_base::random_unique_tuples;
773/// use std::collections::HashMap;
774/// use std::hash::Hash;
775///
776/// random_unique_tuples!(
777///     (pub(crate)),
778///     RandomOrderedUniqueQuadruples,
779///     4,
780///     (I::Item, I::Item, I::Item, I::Item),
781///     random_unique_quadruples,
782///     [0, 1, 2, 3]
783/// );
784///
785/// let qs = random_unique_quadruples(random_unsigned_inclusive_range::<u8>(EXAMPLE_SEED, 1, 10));
786/// assert_eq!(
787///     qs.take(20).collect_vec().as_slice(),
788///     &[
789///         (2, 8, 6, 5),
790///         (7, 5, 3, 9),
791///         (2, 8, 6, 1),
792///         (3, 7, 4, 6),
793///         (3, 10, 6, 9),
794///         (6, 10, 4, 8),
795///         (6, 10, 8, 3),
796///         (10, 2, 9, 5),
797///         (8, 10, 2, 3),
798///         (8, 1, 7, 3),
799///         (2, 6, 1, 10),
800///         (9, 5, 8, 2),
801///         (8, 1, 9, 10),
802///         (7, 3, 8, 1),
803///         (3, 2, 5, 4),
804///         (3, 8, 4, 1),
805///         (9, 7, 6, 3),
806///         (5, 7, 8, 6),
807///         (5, 3, 9, 4),
808///         (9, 10, 4, 6)
809///     ]
810/// );
811/// ```
812pub mod random;