mirror of
https://github.com/tiffany352/rink-rs
synced 2024-11-10 13:44:15 +00:00
Rename derivatives -> factorize; deduplicate
This commit is contained in:
parent
60b3fef18e
commit
e54edca635
5 changed files with 69 additions and 71 deletions
|
@ -1,58 +0,0 @@
|
|||
use std::collections::{BTreeMap, BinaryHeap};
|
||||
use eval::Context;
|
||||
use std::rc::Rc;
|
||||
use number::{Number, Unit};
|
||||
use std::cmp;
|
||||
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
pub struct Deriv(pub usize, pub Vec<Rc<String>>);
|
||||
|
||||
impl cmp::PartialOrd for Deriv {
|
||||
fn partial_cmp(&self, other: &Deriv) -> Option<cmp::Ordering> {
|
||||
Some(self.0.cmp(&other.0).reverse())
|
||||
}
|
||||
}
|
||||
|
||||
impl cmp::Ord for Deriv {
|
||||
fn cmp(&self, other: &Deriv) -> cmp::Ordering {
|
||||
self.partial_cmp(other).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn derivatives(ctx: &Context, value: &Number, aliases: &BTreeMap<Unit, Rc<String>>)
|
||||
-> BinaryHeap<Deriv> {
|
||||
if value.1.len() == 0 {
|
||||
let mut map = BinaryHeap::new();
|
||||
map.push(Deriv(0, vec![]));
|
||||
return map;
|
||||
}
|
||||
let mut candidates: BinaryHeap<Deriv> = BinaryHeap::new();
|
||||
let value_score = value.complexity_score();
|
||||
for (unit, name) in aliases.iter().rev() {
|
||||
use gmp::mpq::Mpq;
|
||||
|
||||
let res = (value / &Number(Mpq::one(), unit.clone())).unwrap();
|
||||
//if res.1.len() >= value.1.len() {
|
||||
let score = res.complexity_score();
|
||||
// we are not making the unit any simpler
|
||||
if score >= value_score {
|
||||
continue
|
||||
}
|
||||
let res = derivatives(ctx, &res, aliases);
|
||||
for Deriv(score, mut vec) in res {
|
||||
vec.push(name.clone());
|
||||
candidates.push(Deriv(score + 1, vec));
|
||||
}
|
||||
let mut next = BinaryHeap::new();
|
||||
for _ in 0..10 {
|
||||
if let Some(v) = candidates.pop() {
|
||||
next.push(v);
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
candidates = next;
|
||||
}
|
||||
assert!(candidates.len() <= 10);
|
||||
candidates
|
||||
}
|
21
src/eval.rs
21
src/eval.rs
|
@ -7,7 +7,7 @@ use date;
|
|||
use unit_defs::DatePattern;
|
||||
use std::ops::{Add, Div, Mul, Neg, Sub};
|
||||
use std::rc::Rc;
|
||||
use derivatives::{derivatives, Deriv};
|
||||
use factorize::{factorize, Factors};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Value {
|
||||
|
@ -324,7 +324,7 @@ impl Context {
|
|||
})
|
||||
}),
|
||||
Expr::Convert(_, _) => Err(format!("Conversions (->) must be top-level expressions")),
|
||||
Expr::Derivatives(_) => Err(format!("Derivatives must be top-level expressions")),
|
||||
Expr::Factorize(_) => Err(format!("Derivatives must be top-level expressions")),
|
||||
Expr::Equals(_, ref right) => self.eval(right),
|
||||
Expr::Call(ref name, ref args) => {
|
||||
let args = try!(args.iter().map(|x| self.eval(x)).collect::<Result<Vec<_>, _>>());
|
||||
|
@ -416,7 +416,7 @@ impl Context {
|
|||
Err(format!("Temperature conversions must not be compound units")),
|
||||
Expr::Date(_) => Err(format!("Dates are not allowed in the right hand side of conversions")),
|
||||
Expr::Convert(_, _) => Err(format!("Conversions are not allowed in the right hand of conversions")),
|
||||
Expr::Derivatives(_) => Err(format!("Derivatives are not allowed in the right hand of conversions")),
|
||||
Expr::Factorize(_) => Err(format!("Derivatives are not allowed in the right hand of conversions")),
|
||||
Expr::Error(ref e) => Err(e.clone()),
|
||||
}
|
||||
}
|
||||
|
@ -561,7 +561,7 @@ impl Context {
|
|||
(Err(e), _, _) => Err(e),
|
||||
(_, _, Err(e)) => Err(e),
|
||||
},
|
||||
Expr::Derivatives(ref expr) => {
|
||||
Expr::Factorize(ref expr) => {
|
||||
let val = try!(self.eval(expr));
|
||||
let val = match val {
|
||||
Value::Number(val) => val,
|
||||
|
@ -570,18 +570,21 @@ impl Context {
|
|||
let aliases = self.aliases.iter()
|
||||
.map(|(a, b)| (a.clone(), Rc::new(b.clone())))
|
||||
.collect::<BTreeMap<_, _>>();
|
||||
let derivs = derivatives(self, &val, &aliases);
|
||||
let derivs = derivs.into_iter().map(|Deriv(_score, names)| {
|
||||
let results = factorize(self, &val, &aliases);
|
||||
let mut results = results.into_sorted_vec();
|
||||
results.dedup();
|
||||
let results = results.into_iter().map(|Factors(_score, names)| {
|
||||
let first = names.first().cloned();
|
||||
names.into_iter().skip(1).fold(
|
||||
first.map(|x| (**x).to_owned()).unwrap_or(String::new()),
|
||||
|a, x| format!("{} {}", a, x))
|
||||
}).collect::<Vec<_>>();
|
||||
let first = derivs.first().cloned();
|
||||
let derivs = derivs.into_iter().skip(1).fold(
|
||||
let first = results.first().cloned();
|
||||
let len = results.len();
|
||||
let results = results.into_iter().skip(1).fold(
|
||||
first.unwrap_or(String::new()),
|
||||
|a, x| format!("{}; {}", a, x));
|
||||
Ok(format!("Possible derivatives: {}", derivs))
|
||||
Ok(format!("Factorizations: {}{}", results, if len < 10 {""} else {"; ..."}))
|
||||
},
|
||||
_ => {
|
||||
let val = try!(self.eval(expr));
|
||||
|
|
53
src/factorize.rs
Normal file
53
src/factorize.rs
Normal file
|
@ -0,0 +1,53 @@
|
|||
use std::collections::{BTreeMap, BinaryHeap};
|
||||
use eval::Context;
|
||||
use std::rc::Rc;
|
||||
use number::{Number, Unit};
|
||||
use std::cmp;
|
||||
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
pub struct Factors(pub usize, pub Vec<Rc<String>>);
|
||||
|
||||
impl cmp::PartialOrd for Factors {
|
||||
fn partial_cmp(&self, other: &Factors) -> Option<cmp::Ordering> {
|
||||
Some(self.0.cmp(&other.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl cmp::Ord for Factors {
|
||||
fn cmp(&self, other: &Factors) -> cmp::Ordering {
|
||||
self.partial_cmp(other).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn factorize(ctx: &Context, value: &Number, aliases: &BTreeMap<Unit, Rc<String>>)
|
||||
-> BinaryHeap<Factors> {
|
||||
if value.1.len() == 0 {
|
||||
let mut map = BinaryHeap::new();
|
||||
map.push(Factors(0, vec![]));
|
||||
return map;
|
||||
}
|
||||
let mut candidates: BinaryHeap<Factors> = BinaryHeap::new();
|
||||
let value_score = value.complexity_score();
|
||||
for (unit, name) in aliases.iter().rev() {
|
||||
use gmp::mpq::Mpq;
|
||||
|
||||
let res = (value / &Number(Mpq::one(), unit.clone())).unwrap();
|
||||
//if res.1.len() >= value.1.len() {
|
||||
let score = res.complexity_score();
|
||||
// we are not making the unit any simpler
|
||||
if score >= value_score {
|
||||
continue
|
||||
}
|
||||
let res = factorize(ctx, &res, aliases);
|
||||
for Factors(score, mut vec) in res {
|
||||
vec.push(name.clone());
|
||||
vec.sort();
|
||||
candidates.push(Factors(score + 1, vec));
|
||||
}
|
||||
let mut next = candidates.into_sorted_vec();
|
||||
next.dedup();
|
||||
candidates = next.into_iter().take(10).collect();
|
||||
}
|
||||
assert!(candidates.len() <= 10);
|
||||
candidates
|
||||
}
|
|
@ -39,7 +39,7 @@ pub mod unit_defs;
|
|||
pub mod eval;
|
||||
pub mod number;
|
||||
pub mod date;
|
||||
pub mod derivatives;
|
||||
pub mod factorize;
|
||||
|
||||
pub use number::Number;
|
||||
pub use eval::{Context, Value};
|
||||
|
|
|
@ -301,7 +301,7 @@ pub enum Expr {
|
|||
Equals(Box<Expr>, Box<Expr>),
|
||||
Suffix(SuffixOp, Box<Expr>),
|
||||
Call(String, Vec<Expr>),
|
||||
Derivatives(Box<Expr>),
|
||||
Factorize(Box<Expr>),
|
||||
DegC,
|
||||
DegF,
|
||||
DegRe,
|
||||
|
@ -502,9 +502,9 @@ fn parse_eq(mut iter: &mut Iter) -> Expr {
|
|||
|
||||
pub fn parse_expr(mut iter: &mut Iter) -> Expr {
|
||||
match iter.peek().cloned() {
|
||||
Some(Token::Ident(ref s)) if s == "derivatives" => {
|
||||
Some(Token::Ident(ref s)) if s == "factorize" => {
|
||||
iter.next();
|
||||
return Expr::Derivatives(Box::new(parse_eq(iter)))
|
||||
return Expr::Factorize(Box::new(parse_eq(iter)))
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue