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