equation_solver/
equation.rs

1use std::collections::HashSet;
2
3use crate::{
4    error::{EquationError, EquationErrorType},
5    item::{Item, Operator},
6    parse::ParseStream,
7};
8
9/// The equation Struct is used to solve an equation.
10#[derive(Debug)]
11pub struct Equation {
12    inner: Group,
13}
14
15/// The Group struct is used to represent a group of items (like those inside of bracets).
16#[derive(Debug, Clone)]
17pub struct Group {
18    items: Vec<Item>,
19}
20
21// private little thing for equation validation
22enum Previous {
23    Function,
24    Value,
25    None,
26}
27
28impl Group {
29    /// Creates an empty group.
30    pub fn new() -> Group {
31        Group { items: Vec::new() }
32    }
33    /// Checks if the group is a valid equation.
34    pub fn validate(&self) -> Result<(), EquationError> {
35        let mut previous = Previous::None;
36        let mut x = self.items.iter();
37        while let Some(next) = x.next() {
38            match (&previous, next) {
39                (Previous::None, Item::Value(_) | Item::Variable(_) | Item::Group(_)) => {
40                    previous = Previous::Value
41                }
42                (Previous::None, Item::Operator(Operator::Functional(_))) => {
43                    previous = Previous::Function
44                }
45                (Previous::Value, Item::Operator(Operator::LeftAssociative(_))) => {
46                    previous = Previous::Function
47                }
48                (Previous::Function, Item::Group(_) | Item::Variable(_) | Item::Value(_)) => {
49                    previous = Previous::Value
50                }
51
52                (_, _) => {
53                    return Err(EquationError::new(
54                        "Unexpected token".to_string(),
55                        EquationErrorType::UnexpectedToken,
56                    ))
57                }
58            }
59        }
60        Ok(())
61    }
62    /// Sets the value of a variable in the group.
63    pub fn set_value(&mut self, variable: &str, item: Item) {
64        let mut x = self.items.iter_mut();
65        while let Some(next) = x.next() {
66            match next {
67                Item::Variable(val) if val == variable => {
68                    *next = item.clone();
69                }
70                Item::Group(val) => {
71                    val.set_value(variable, item.clone());
72                }
73                _ => {}
74            }
75        }
76    }
77    /// Evaluates the value of the group
78    pub fn evaluate(&self) -> Result<f64, EquationError> {
79        // first lets iter over all groups and evaluate them into values
80        let mut items = self.items.clone();
81        let mut i = 0;
82        while i < items.len() {
83            if let Some(Item::Group(val)) = items.get(i) {
84                // this is recursive but should never exceed the limit as long as someone doesnt do something stupid...
85                let val = val.evaluate()?;
86                items[i] = Item::Value(val);
87            }
88            i += 1;
89        }
90        // now we evaluate all functions
91        let mut i = 0;
92        while i < items.len() - 1 {
93            let next = items.get(i).unwrap().clone();
94            if let Item::Operator(Operator::Functional(func)) = next {
95                let to_eval = items.remove(i + 1);
96                if let Item::Value(to_eval) = to_eval {
97                    let val = func.evaluate(to_eval);
98                    items[i] = Item::Value(val);
99                } else if let Item::Variable(var) = to_eval {
100                    return Err(EquationError::new(
101                        format!("Variable {} not set", var),
102                        EquationErrorType::UnsetVariable,
103                    ));
104                } else {
105                    return Err(EquationError::new(
106                        format!("Unexpected token {:?}", to_eval),
107                        EquationErrorType::UnexpectedToken,
108                    ));
109                }
110            }
111            i += 1;
112        }
113        // functions
114        let mut i = 1;
115        for order in 0..3 {
116            while i < items.len() - 1 {
117                let next = items.get(i).unwrap().clone();
118                if let Item::Operator(Operator::LeftAssociative(op)) = next {
119                    if op.is_of_order(&order) {
120                        let right = items.remove(i + 1);
121                        let left = items.remove(i - 1);
122                        let x = (left, right);
123                        // println!("{:?}", x);
124                        if let (Item::Value(left), Item::Value(right)) = x.clone() {
125                            let val = op.eval(left, right);
126                            items[i - 1] = Item::Value(val);
127                        } else {
128                            return Err(EquationError::new(
129                                "Incorrect Tokens".to_string(),
130                                EquationErrorType::UnexpectedToken,
131                            ));
132                        }
133                        continue;
134                    }
135                }
136                i += 1;
137            }
138            i = 1;
139        }
140        if let Some(Item::Value(val)) = items.get(0) {
141            Ok(*val)
142        } else {
143            Err(EquationError::new(
144                "Unexpected Tokens".to_string(),
145                EquationErrorType::UnexpectedToken,
146            ))
147        }
148    }
149    /// Lists the variables that are not set in an equation
150    pub fn list_vars(&self) -> HashSet<String> {
151        let mut vars = HashSet::new();
152        for item in self.items.iter() {
153            match item {
154                Item::Variable(val) => {
155                    vars.insert(val.clone());
156                }
157                Item::Group(val) => {
158                    vars.extend(val.list_vars());
159                }
160                _ => {}
161            }
162        }
163        vars
164    }
165}
166
167impl From<Vec<Item>> for Group {
168    fn from(val: Vec<Item>) -> Self {
169        Group { items: val }
170    }
171}
172
173impl Equation {
174    /// Creates a new equation from a string.
175    pub fn new(s: impl Into<String>) -> Result<Equation, EquationError> {
176        let parse_stream = ParseStream::new(s.into());
177        let mut group: Group = parse_stream.parse_items()?.into();
178        // group.validate()?;
179        // set consts
180        group.set_value("pi", std::f64::consts::PI.into());
181        group.set_value("e", std::f64::consts::E.into());
182        group.set_value("tau", std::f64::consts::TAU.into());
183        group.set_value("deg", (std::f64::consts::PI / 180.0).into());
184        Ok(Equation { inner: group })
185    }
186    /// Sets the value of a variable in the equation.
187    pub fn set_value(&mut self, variable: &str, value: f64) -> &mut Self {
188        self.inner.set_value(variable, Item::Value(value));
189        self
190    }
191    /// Sets the value of a variable to an equation. Note: The equation's variables used in the original equation will be used, and no already set values will be overwriten.
192    pub fn set_equation(&mut self, variable: &str, equation: Self) -> &mut Self {
193        self.inner.set_value(variable, Item::Group(equation.inner));
194        self
195    }
196    /// Evaluates the equation.
197    pub fn evaluate(&self) -> Result<f64, EquationError> {
198        self.inner.evaluate()
199    }
200    /// Gives a HashSet of all variables (that are not set) in the equation.
201    pub fn list_vars(&self) -> HashSet<String> {
202        self.inner.list_vars()
203    }
204}