hakari/explain/
simplify.rs1use itertools::Itertools;
5#[cfg(feature = "cli-support")]
6use owo_colors::{OwoColorize, Style};
7#[cfg(feature = "cli-support")]
8use std::fmt;
9use std::{collections::BTreeSet, hash::Hash};
10
11#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
12pub(super) enum Simple<T> {
13 Any,
14 Some(T),
15}
16
17impl<T> Simple<T> {
18 #[cfg(feature = "cli-support")]
19 pub(super) fn display_with<'simple, F>(
20 &'simple self,
21 star_style: &'simple Style,
22 display_fn: F,
23 ) -> SimpleDisplay<'simple, T, F>
24 where
25 F: Fn(&T, &mut fmt::Formatter) -> fmt::Result,
26 {
27 SimpleDisplay {
28 simple: self,
29 star_style,
30 display_fn,
31 }
32 }
33}
34
35#[cfg(feature = "cli-support")]
36pub(super) struct SimpleDisplay<'simple, T, F> {
37 simple: &'simple Simple<T>,
38 star_style: &'simple Style,
39 display_fn: F,
40}
41
42#[cfg(feature = "cli-support")]
43impl<T, F> fmt::Display for SimpleDisplay<'_, T, F>
44where
45 F: Fn(&T, &mut fmt::Formatter) -> fmt::Result,
46{
47 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48 match self.simple {
49 Simple::Any => write!(f, "{}", "*".style(*self.star_style)),
50 Simple::Some(val) => (self.display_fn)(val, f),
51 }
52 }
53}
54
55pub(super) fn simplify3<A, B, C>(
56 input: &BTreeSet<(A, B, C)>,
57 (n_a, n_b, n_c): (usize, usize, usize),
58) -> Vec<(Simple<A>, Simple<B>, Simple<C>)>
59where
60 A: Eq + Hash + Ord + Clone,
61 B: Eq + Hash + Ord + Clone,
62 C: Eq + Hash + Ord + Clone,
63{
64 if input.len() == (n_a * n_b * n_c) {
68 return vec![(Simple::Any, Simple::Any, Simple::Any)];
69 }
70
71 let mut res = vec![];
72 let group_map = input.iter().map(|(a, b, c)| (a, (b, c))).into_group_map();
73
74 for (a, val) in group_map.into_iter().sorted() {
77 if val.len() == n_b * n_c {
78 res.push((Simple::Some(a.clone()), Simple::Any, Simple::Any));
79 } else {
80 for (b, val) in val.into_iter().into_group_map().into_iter().sorted() {
81 if val.len() == n_c {
82 res.push((
83 Simple::Some(a.clone()),
84 Simple::Some(b.clone()),
85 Simple::Any,
86 ));
87 } else {
88 for c in val {
89 res.push((
90 Simple::Some(a.clone()),
91 Simple::Some(b.clone()),
92 Simple::Some(c.clone()),
93 ));
94 }
95 }
96 }
97 }
98 }
99
100 res
101}
102
103pub(super) fn simplify1<A>(input: &BTreeSet<A>, n_a: usize) -> Vec<Simple<A>>
104where
105 A: Eq + Hash + Ord + Clone,
106{
107 if input.len() == n_a {
108 vec![Simple::Any]
109 } else {
110 input.iter().map(|a| Simple::Some(a.clone())).collect()
111 }
112}