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;