// 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::get_sample_output_types; use itertools::Itertools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::iterators::bit_distributor::BitDistributorOutputType; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::{exhaustive_positive_primitive_ints, exhaustive_unsigneds}; use malachite_base::vecs::exhaustive::{ exhaustive_vecs_fixed_length_1_input, exhaustive_vecs_fixed_length_2_inputs, }; use std::fmt::Debug; use std::iter::empty; fn exhaustive_vecs_fixed_length_1_input_helper>( xs: &I, len: usize, out_len: Option, out: &[&[T]], ) where T: Clone + Debug + Eq, { let output_types = get_sample_output_types(len); let xss = exhaustive_vecs_fixed_length_1_input(xs.clone(), &output_types[0]); let xss_prefix = xss.clone().take(20).collect_vec(); assert_eq!( xss_prefix .iter() .map(Vec::as_slice) .collect_vec() .as_slice(), out ); if let Some(out_len) = out_len { assert_eq!(xss.count(), out_len); } for alt_output_types in &output_types[1..] { let xss = exhaustive_vecs_fixed_length_1_input(xs.clone(), alt_output_types); xss.clone().take(20).for_each(drop); if let Some(out_len) = out_len { assert_eq!(xss.count(), out_len); } } } #[test] fn test_exhaustive_vecs_fixed_length_1_input() { exhaustive_vecs_fixed_length_1_input_helper(&nevers(), 2, Some(0), &[]); exhaustive_vecs_fixed_length_1_input_helper( &exhaustive_unsigneds::(), 2, Some(1 << 16), &[ &[0, 0], &[0, 1], &[1, 0], &[1, 1], &[0, 2], &[0, 3], &[1, 2], &[1, 3], &[2, 0], &[2, 1], &[3, 0], &[3, 1], &[2, 2], &[2, 3], &[3, 2], &[3, 3], &[0, 4], &[0, 5], &[1, 4], &[1, 5], ], ); exhaustive_vecs_fixed_length_1_input_helper( &exhaustive_positive_primitive_ints::(), 2, None, &[ &[1, 1], &[1, 2], &[2, 1], &[2, 2], &[1, 3], &[1, 4], &[2, 3], &[2, 4], &[3, 1], &[3, 2], &[4, 1], &[4, 2], &[3, 3], &[3, 4], &[4, 3], &[4, 4], &[1, 5], &[1, 6], &[2, 5], &[2, 6], ], ); exhaustive_vecs_fixed_length_1_input_helper( &['x', 'y', 'z'].iter().copied(), 2, Some(9), &[ &['x', 'x'], &['x', 'y'], &['y', 'x'], &['y', 'y'], &['x', 'z'], &['y', 'z'], &['z', 'x'], &['z', 'y'], &['z', 'z'], ], ); exhaustive_vecs_fixed_length_1_input_helper( &['x', 'y', 'z'].iter().copied(), 3, Some(27), &[ &['x', 'x', 'x'], &['x', 'x', 'y'], &['x', 'y', 'x'], &['x', 'y', 'y'], &['y', 'x', 'x'], &['y', 'x', 'y'], &['y', 'y', 'x'], &['y', 'y', 'y'], &['x', 'x', 'z'], &['x', 'y', 'z'], &['y', 'x', 'z'], &['y', 'y', 'z'], &['x', 'z', 'x'], &['x', 'z', 'y'], &['y', 'z', 'x'], &['y', 'z', 'y'], &['x', 'z', 'z'], &['y', 'z', 'z'], &['z', 'x', 'x'], &['z', 'x', 'y'], ], ); exhaustive_vecs_fixed_length_1_input_helper( &exhaustive_ascii_chars(), 3, None, &[ &['a', 'a', 'a'], &['a', 'a', 'b'], &['a', 'b', 'a'], &['a', 'b', 'b'], &['b', 'a', 'a'], &['b', 'a', 'b'], &['b', 'b', 'a'], &['b', 'b', 'b'], &['a', 'a', 'c'], &['a', 'a', 'd'], &['a', 'b', 'c'], &['a', 'b', 'd'], &['b', 'a', 'c'], &['b', 'a', 'd'], &['b', 'b', 'c'], &['b', 'b', 'd'], &['a', 'c', 'a'], &['a', 'c', 'b'], &['a', 'd', 'a'], &['a', 'd', 'b'], ], ); } fn exhaustive_vecs_fixed_length_2_inputs_helper< T, I: Clone + Iterator, J: Clone + Iterator, >( xs: &I, ys: &J, len: usize, input_indices: &[usize], out_len: Option, out: &[&[T]], ) where T: Clone + Debug + Eq, { let output_types = get_sample_output_types(len); let output_configs: Vec<(BitDistributorOutputType, usize)> = output_types[0] .iter() .copied() .zip(input_indices.iter().copied()) .collect(); let xss = exhaustive_vecs_fixed_length_2_inputs(xs.clone(), ys.clone(), &output_configs); let xss_prefix = xss.clone().take(20).collect_vec(); assert_eq!( xss_prefix .iter() .map(Vec::as_slice) .collect_vec() .as_slice(), out ); if let Some(out_len) = out_len { assert_eq!(xss.count(), out_len); } for alt_output_types in &output_types[1..] { let output_configs: Vec<(BitDistributorOutputType, usize)> = alt_output_types .iter() .copied() .zip(input_indices.iter().copied()) .collect(); let xss = exhaustive_vecs_fixed_length_2_inputs(xs.clone(), ys.clone(), &output_configs); xss.clone().take(20).for_each(drop); if let Some(out_len) = out_len { assert_eq!(xss.count(), out_len); } } } #[test] fn test_exhaustive_vecs_fixed_length_2_inputs() { exhaustive_vecs_fixed_length_2_inputs_helper(&nevers(), &nevers(), 2, &[0, 1], Some(0), &[]); exhaustive_vecs_fixed_length_2_inputs_helper( &empty(), &exhaustive_unsigneds::(), 2, &[0, 1], Some(0), &[], ); exhaustive_vecs_fixed_length_2_inputs_helper( &exhaustive_unsigneds::(), &exhaustive_positive_primitive_ints::(), 2, &[0, 1], None, &[ &[0, 1], &[0, 2], &[1, 1], &[1, 2], &[0, 3], &[0, 4], &[1, 3], &[1, 4], &[2, 1], &[2, 2], &[3, 1], &[3, 2], &[2, 3], &[2, 4], &[3, 3], &[3, 4], &[0, 5], &[0, 6], &[1, 5], &[1, 6], ], ); exhaustive_vecs_fixed_length_2_inputs_helper( &exhaustive_ascii_chars(), &['x', 'y', 'z'].iter().copied(), 2, &[0, 1], Some(384), &[ &['a', 'x'], &['a', 'y'], &['b', 'x'], &['b', 'y'], &['a', 'z'], &['b', 'z'], &['c', 'x'], &['c', 'y'], &['d', 'x'], &['d', 'y'], &['c', 'z'], &['d', 'z'], &['e', 'x'], &['e', 'y'], &['f', 'x'], &['f', 'y'], &['e', 'z'], &['f', 'z'], &['g', 'x'], &['g', 'y'], ], ); exhaustive_vecs_fixed_length_2_inputs_helper( &exhaustive_ascii_chars(), &['x', 'y', 'z'].iter().copied(), 3, &[0, 1, 1], Some(1152), &[ &['a', 'x', 'x'], &['a', 'x', 'y'], &['a', 'y', 'x'], &['a', 'y', 'y'], &['b', 'x', 'x'], &['b', 'x', 'y'], &['b', 'y', 'x'], &['b', 'y', 'y'], &['a', 'x', 'z'], &['a', 'y', 'z'], &['b', 'x', 'z'], &['b', 'y', 'z'], &['a', 'z', 'x'], &['a', 'z', 'y'], &['b', 'z', 'x'], &['b', 'z', 'y'], &['a', 'z', 'z'], &['b', 'z', 'z'], &['c', 'x', 'x'], &['c', 'x', 'y'], ], ); exhaustive_vecs_fixed_length_2_inputs_helper( &exhaustive_ascii_chars(), &['x', 'y', 'z'].iter().copied(), 3, &[0, 1, 0], Some(49152), &[ &['a', 'x', 'a'], &['a', 'x', 'b'], &['a', 'y', 'a'], &['a', 'y', 'b'], &['b', 'x', 'a'], &['b', 'x', 'b'], &['b', 'y', 'a'], &['b', 'y', 'b'], &['a', 'x', 'c'], &['a', 'x', 'd'], &['a', 'y', 'c'], &['a', 'y', 'd'], &['b', 'x', 'c'], &['b', 'x', 'd'], &['b', 'y', 'c'], &['b', 'y', 'd'], &['a', 'z', 'a'], &['a', 'z', 'b'], &['b', 'z', 'a'], &['b', 'z', 'b'], ], ); } #[test] #[should_panic] fn exhaustive_vecs_fixed_length_2_inputs_fail_1() { exhaustive_vecs_fixed_length_2_inputs(0..2, 0..3, &[]); } #[test] #[should_panic] fn exhaustive_vecs_fixed_length_2_inputs_fail_2() { exhaustive_vecs_fixed_length_2_inputs(0..2, 0..3, &[(BitDistributorOutputType::normal(1), 0)]); } #[test] #[should_panic] fn exhaustive_vecs_fixed_length_2_inputs_fail_3() { exhaustive_vecs_fixed_length_2_inputs(0..2, 0..3, &[(BitDistributorOutputType::normal(1), 1)]); } #[test] #[should_panic] fn exhaustive_vecs_fixed_length_2_inputs_fail_4() { exhaustive_vecs_fixed_length_2_inputs( 0..2, 0..3, &[ (BitDistributorOutputType::normal(1), 0), (BitDistributorOutputType::normal(1), 1), (BitDistributorOutputType::normal(1), 2), ], ); }