// Copyright © 2024 Mikhail Hogrefe
//
// This file is part of Malachite.
//
// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
// 3 of the License, or (at your option) any later version. See .
use crate::extra_variadic::exhaustive_triples_from_single;
use crate::get_sample_output_types;
use itertools::Itertools;
use malachite_base::bools::exhaustive::exhaustive_bools;
use malachite_base::nevers::nevers;
use malachite_base::num::exhaustive::exhaustive_unsigneds;
use malachite_base::options::exhaustive::exhaustive_somes;
use malachite_base::orderings::exhaustive::exhaustive_orderings;
use malachite_base::tuples::exhaustive::{
exhaustive_pairs, exhaustive_pairs_custom_output, exhaustive_pairs_from_single,
exhaustive_triples, exhaustive_triples_custom_output,
};
use std::cmp::Ordering::*;
use std::fmt::Debug;
use std::iter::once;
#[allow(clippy::needless_pass_by_value)]
fn exhaustive_pairs_helper<
X: Clone + Debug + Eq,
I: Clone + Iterator- ,
Y: Clone + Debug + Eq,
J: Clone + Iterator
- ,
>(
xs: I,
ys: J,
out_len: usize,
out: &[(X, Y)],
) {
let ps = exhaustive_pairs(xs.clone(), ys.clone());
assert_eq!(ps.clone().take(20).collect_vec(), out);
assert_eq!(ps.count(), out_len);
let output_types = get_sample_output_types(2);
let ps = exhaustive_pairs_custom_output(
xs.clone(),
ys.clone(),
output_types[0][0],
output_types[0][1],
);
assert_eq!(ps.clone().take(20).collect_vec(), out);
assert_eq!(ps.count(), out_len);
for alt_output_types in &output_types[1..] {
let ps = exhaustive_pairs_custom_output(
xs.clone(),
ys.clone(),
alt_output_types[0],
alt_output_types[1],
);
ps.clone().take(20).for_each(drop);
assert_eq!(ps.count(), out_len);
}
}
#[test]
fn test_exhaustive_pairs_and_exhaustive_pairs_custom_output() {
exhaustive_pairs_helper(nevers(), nevers(), 0, &[]);
exhaustive_pairs_helper(nevers(), 0..4, 0, &[]);
exhaustive_pairs_helper(once('a'), once(1), 1, &[('a', 1)]);
exhaustive_pairs_helper(
once('a'),
0..4,
4,
&[('a', 0), ('a', 1), ('a', 2), ('a', 3)],
);
exhaustive_pairs_helper(
exhaustive_unsigneds::(),
'a'..'e',
1024,
&[
(0, 'a'),
(0, 'b'),
(1, 'a'),
(1, 'b'),
(0, 'c'),
(0, 'd'),
(1, 'c'),
(1, 'd'),
(2, 'a'),
(2, 'b'),
(3, 'a'),
(3, 'b'),
(2, 'c'),
(2, 'd'),
(3, 'c'),
(3, 'd'),
(4, 'a'),
(4, 'b'),
(5, 'a'),
(5, 'b'),
],
);
exhaustive_pairs_helper(
exhaustive_bools(),
0..4,
8,
&[
(false, 0),
(false, 1),
(true, 0),
(true, 1),
(false, 2),
(false, 3),
(true, 2),
(true, 3),
],
);
exhaustive_pairs_helper(
'a'..'f',
0..3,
15,
&[
('a', 0),
('a', 1),
('b', 0),
('b', 1),
('a', 2),
('b', 2),
('c', 0),
('c', 1),
('d', 0),
('d', 1),
('c', 2),
('d', 2),
('e', 0),
('e', 1),
('e', 2),
],
);
exhaustive_pairs_helper(
['a', 'b', 'c'].iter().copied(),
exhaustive_orderings(),
9,
&[
('a', Equal),
('a', Less),
('b', Equal),
('b', Less),
('a', Greater),
('b', Greater),
('c', Equal),
('c', Less),
('c', Greater),
],
);
exhaustive_pairs_helper(
exhaustive_pairs(exhaustive_orderings(), exhaustive_bools()),
exhaustive_triples_from_single([Less, Greater].iter().copied()),
48,
&[
((Equal, false), (Less, Less, Less)),
((Equal, false), (Less, Less, Greater)),
((Equal, true), (Less, Less, Less)),
((Equal, true), (Less, Less, Greater)),
((Equal, false), (Less, Greater, Less)),
((Equal, false), (Less, Greater, Greater)),
((Equal, true), (Less, Greater, Less)),
((Equal, true), (Less, Greater, Greater)),
((Less, false), (Less, Less, Less)),
((Less, false), (Less, Less, Greater)),
((Less, true), (Less, Less, Less)),
((Less, true), (Less, Less, Greater)),
((Less, false), (Less, Greater, Less)),
((Less, false), (Less, Greater, Greater)),
((Less, true), (Less, Greater, Less)),
((Less, true), (Less, Greater, Greater)),
((Equal, false), (Greater, Less, Less)),
((Equal, false), (Greater, Less, Greater)),
((Equal, true), (Greater, Less, Less)),
((Equal, true), (Greater, Less, Greater)),
],
);
}
#[allow(clippy::needless_pass_by_value)]
fn exhaustive_triples_helper<
X: Clone + Debug + Eq,
I: Clone + Iterator
- ,
Y: Clone + Debug + Eq,
J: Clone + Iterator
- ,
Z: Clone + Debug + Eq,
K: Clone + Iterator
- ,
>(
xs: I,
ys: J,
zs: K,
out_len: usize,
out: &[(X, Y, Z)],
) {
let ts = exhaustive_triples(xs.clone(), ys.clone(), zs.clone());
assert_eq!(ts.clone().take(20).collect_vec(), out);
assert_eq!(ts.count(), out_len);
let output_types = get_sample_output_types(3);
let ts = exhaustive_triples_custom_output(
xs.clone(),
ys.clone(),
zs.clone(),
output_types[0][0],
output_types[0][1],
output_types[0][2],
);
assert_eq!(ts.clone().take(20).collect_vec(), out);
assert_eq!(ts.count(), out_len);
for alt_output_types in &output_types[1..] {
let ts = exhaustive_triples_custom_output(
xs.clone(),
ys.clone(),
zs.clone(),
alt_output_types[0],
alt_output_types[1],
alt_output_types[2],
);
ts.clone().take(20).for_each(drop);
assert_eq!(ts.count(), out_len);
}
}
#[test]
fn test_exhaustive_triples_and_exhaustive_triples_custom_output() {
exhaustive_triples_helper(nevers(), nevers(), nevers(), 0, &[]);
exhaustive_triples_helper(nevers(), 0..4, 'a'..'f', 0, &[]);
exhaustive_triples_helper(once('a'), once(false), once(5), 1, &[('a', false, 5)]);
exhaustive_triples_helper(
once('a'),
once(false),
0..4,
4,
&[('a', false, 0), ('a', false, 1), ('a', false, 2), ('a', false, 3)],
);
exhaustive_triples_helper(
exhaustive_unsigneds::(),
exhaustive_pairs_from_single(exhaustive_bools()),
'a'..'e',
4096,
&[
(0, (false, false), 'a'),
(0, (false, false), 'b'),
(0, (false, true), 'a'),
(0, (false, true), 'b'),
(1, (false, false), 'a'),
(1, (false, false), 'b'),
(1, (false, true), 'a'),
(1, (false, true), 'b'),
(0, (false, false), 'c'),
(0, (false, false), 'd'),
(0, (false, true), 'c'),
(0, (false, true), 'd'),
(1, (false, false), 'c'),
(1, (false, false), 'd'),
(1, (false, true), 'c'),
(1, (false, true), 'd'),
(0, (true, false), 'a'),
(0, (true, false), 'b'),
(0, (true, true), 'a'),
(0, (true, true), 'b'),
],
);
exhaustive_triples_helper(
exhaustive_bools(),
0..3,
'a'..'d',
18,
&[
(false, 0, 'a'),
(false, 0, 'b'),
(false, 1, 'a'),
(false, 1, 'b'),
(true, 0, 'a'),
(true, 0, 'b'),
(true, 1, 'a'),
(true, 1, 'b'),
(false, 0, 'c'),
(false, 1, 'c'),
(true, 0, 'c'),
(true, 1, 'c'),
(false, 2, 'a'),
(false, 2, 'b'),
(true, 2, 'a'),
(true, 2, 'b'),
(false, 2, 'c'),
(true, 2, 'c'),
],
);
exhaustive_triples_helper(
0..11,
exhaustive_somes(0..12),
'a'..'n',
1716,
&[
(0, Some(0), 'a'),
(0, Some(0), 'b'),
(0, Some(1), 'a'),
(0, Some(1), 'b'),
(1, Some(0), 'a'),
(1, Some(0), 'b'),
(1, Some(1), 'a'),
(1, Some(1), 'b'),
(0, Some(0), 'c'),
(0, Some(0), 'd'),
(0, Some(1), 'c'),
(0, Some(1), 'd'),
(1, Some(0), 'c'),
(1, Some(0), 'd'),
(1, Some(1), 'c'),
(1, Some(1), 'd'),
(0, Some(2), 'a'),
(0, Some(2), 'b'),
(0, Some(3), 'a'),
(0, Some(3), 'b'),
],
);
exhaustive_triples_helper(
['a', 'b', 'c'].iter().copied(),
["xx", "yy", "zz"].iter().copied(),
0..3,
27,
&[
('a', "xx", 0),
('a', "xx", 1),
('a', "yy", 0),
('a', "yy", 1),
('b', "xx", 0),
('b', "xx", 1),
('b', "yy", 0),
('b', "yy", 1),
('a', "xx", 2),
('a', "yy", 2),
('b', "xx", 2),
('b', "yy", 2),
('a', "zz", 0),
('a', "zz", 1),
('b', "zz", 0),
('b', "zz", 1),
('a', "zz", 2),
('b', "zz", 2),
('c', "xx", 0),
('c', "xx", 1),
],
);
}