rink_core/commands/
factorize.rs1use crate::types::{Dimensionality, Number, Numeric};
6use std::cmp;
7use std::collections::{BTreeMap, BinaryHeap};
8use std::rc::Rc;
9
10#[derive(PartialEq, Ord, Eq, Debug)]
11pub struct Factors(pub usize, pub Vec<Rc<String>>);
12
13impl cmp::PartialOrd for Factors {
14 fn partial_cmp(&self, other: &Factors) -> Option<cmp::Ordering> {
15 Some(self.0.cmp(&other.0))
16 }
17}
18
19pub fn factorize(
20 value: &Number,
21 quantities: &BTreeMap<Dimensionality, Rc<String>>,
22) -> BinaryHeap<Factors> {
23 if value.dimless() {
24 let mut map = BinaryHeap::new();
25 map.push(Factors(0, vec![]));
26 return map;
27 }
28 let mut candidates: BinaryHeap<Factors> = BinaryHeap::new();
29 let value_score = value.complexity_score();
30 for (unit, name) in quantities.iter().rev() {
31 let num = Number {
32 value: Numeric::one(),
33 unit: unit.clone(),
34 };
35 let res = (value / &num).unwrap();
36 let score = res.complexity_score();
38 if score >= value_score {
40 continue;
41 }
42 let res = factorize(&res, quantities);
43 for Factors(score, mut vec) in res {
44 vec.push(name.clone());
45 vec.sort();
46 candidates.push(Factors(score + 1, vec));
47 }
48 let mut next = candidates.into_sorted_vec();
49 next.dedup();
50 candidates = next.into_iter().take(10).collect();
51 }
52 assert!(candidates.len() <= 10);
53 candidates
54}