// 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 core::hash::Hash;
use itertools::{chain, Itertools};
use malachite_base::tuples::exhaustive::{
lex_dependent_pairs, lex_dependent_pairs_stop_after_empty_ys,
ExhaustiveDependentPairsYsGenerator,
};
use std::collections::HashMap;
use std::fmt::Debug;
use std::iter::{once, repeat, Cloned};
use std::slice::Iter;
#[derive(Clone, Debug)]
struct DPGeneratorFromMap {
map: HashMap,
}
impl
ExhaustiveDependentPairsYsGenerator>>
for DPGeneratorFromMap
{
#[inline]
fn get_ys(&self, x: &X) -> Cloned> {
self.map[x].iter().cloned()
}
}
fn lex_dependent_pairs_helper(
xs: I,
map: HashMap,
out: &[(I::Item, Y)],
) where
I::Item: Clone + Debug + Eq + Hash,
Y: Clone + Debug + Eq,
{
let xss = lex_dependent_pairs(xs, DPGeneratorFromMap { map })
.take(20)
.collect_vec();
assert_eq!(xss.as_slice(), out);
}
#[test]
fn test_lex_dependent_pairs() {
lex_dependent_pairs_helper(
[1, 2, 3].iter().copied(),
hashmap! {
1 => &[100, 101, 102][..],
2 => &[200, 201, 202][..],
3 => &[300, 301, 302][..]
},
&[(1, 100), (1, 101), (1, 102), (2, 200), (2, 201), (2, 202), (3, 300), (3, 301), (3, 302)],
);
lex_dependent_pairs_helper(
["cat", "dog", "mouse", "dog", "cat"].iter().copied(),
hashmap! { "cat" => &[2, 3, 4][..], "dog" => &[20][..], "mouse" => &[30, 40][..] },
&[
("cat", 2),
("cat", 3),
("cat", 4),
("dog", 20),
("mouse", 30),
("mouse", 40),
("dog", 20),
("cat", 2),
("cat", 3),
("cat", 4),
],
);
lex_dependent_pairs_helper(
[1, 2, 3, 2, 3, 2, 2].iter().copied(),
hashmap! { 1 => &[100, 101, 102][..], 2 => &[][..], 3 => &[300, 301, 302][..] },
&[(1, 100), (1, 101), (1, 102), (3, 300), (3, 301), (3, 302), (3, 300), (3, 301), (3, 302)],
);
lex_dependent_pairs_helper(
[].iter().copied(),
hashmap! { 1 => &[100, 101, 102][..], 2 => &[][..], 3 => &[300, 301, 302][..] },
&[],
);
lex_dependent_pairs_helper(
[2, 2, 2, 2, 2].iter().copied(),
hashmap! { 1 => &[100, 101, 102][..], 2 => &[][..], 3 => &[300, 301, 302][..] },
&[],
);
}
fn lex_dependent_pairs_stop_after_empty_ys_helper(
xs: I,
map: HashMap,
out: &[(I::Item, Y)],
) where
I::Item: Clone + Debug + Eq + Hash,
Y: Clone + Debug + Eq,
{
let xss = lex_dependent_pairs_stop_after_empty_ys(xs, DPGeneratorFromMap { map })
.take(20)
.collect_vec();
assert_eq!(xss.as_slice(), out);
}
#[test]
fn test_lex_dependent_pairs_stop_after_empty_ys() {
lex_dependent_pairs_stop_after_empty_ys_helper(
[1, 2, 3].iter().copied(),
hashmap! {
1 => &[100, 101, 102][..],
2 => &[200, 201, 202][..],
3 => &[300, 301, 302][..]
},
&[(1, 100), (1, 101), (1, 102), (2, 200), (2, 201), (2, 202), (3, 300), (3, 301), (3, 302)],
);
lex_dependent_pairs_stop_after_empty_ys_helper(
["cat", "dog", "mouse", "dog", "cat"].iter().copied(),
hashmap! { "cat" => &[2, 3, 4][..], "dog" => &[20][..], "mouse" => &[30, 40][..] },
&[
("cat", 2),
("cat", 3),
("cat", 4),
("dog", 20),
("mouse", 30),
("mouse", 40),
("dog", 20),
("cat", 2),
("cat", 3),
("cat", 4),
],
);
// Notice difference from `lex_dependent_pairs`
lex_dependent_pairs_stop_after_empty_ys_helper(
[1, 2, 3, 2, 3, 2, 2].iter().copied(),
hashmap! { 1 => &[100, 101, 102][..], 2 => &[][..], 3 => &[300, 301, 302][..] },
&[(1, 100), (1, 101), (1, 102)],
);
lex_dependent_pairs_stop_after_empty_ys_helper(
[].iter().copied(),
hashmap! { 1 => &[100, 101, 102][..], 2 => &[][..], 3 => &[300, 301, 302][..] },
&[],
);
lex_dependent_pairs_stop_after_empty_ys_helper(
[2, 2, 2, 2, 2].iter().copied(),
hashmap! { 1 => &[100, 101, 102][..], 2 => &[][..], 3 => &[300, 301, 302][..] },
&[],
);
// With `lex_dependent_pairs` this would hang
lex_dependent_pairs_stop_after_empty_ys_helper(
chain(once(3), repeat(2)),
hashmap! { 1 => &[100, 101, 102][..], 2 => &[][..], 3 => &[300, 301, 302][..] },
&[(3, 300), (3, 301), (3, 302)],
);
}