-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathArithmeticTree.java
121 lines (94 loc) · 3.18 KB
/
ArithmeticTree.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class ArithmeticTree {
private class Node {
private String content;
private Node left;
private Node right;
public Node(String content) { this.content = content; }
public boolean isOperator() { return !isNumber() && !isVariable(); }
public boolean isNumber() { return content.matches("^([0-9](.[0-9])?)*$"); }
public boolean isVariable() { return content.matches("^[a-zA-Z]*$"); }
}
String formula;
Map<String, Double> variables;
Node root;
// private constructor: cannot be called outside of this class
private ArithmeticTree() {
formula = "";
variables = new HashMap<>();
}
// creates the default arithmetic tree: "+ * a 2.1 - 3 b"
public static ArithmeticTree createDefault() {
return createFormula("+ * a 2.1 - 3 b");
}
// deserializes the string "s" and returns a new tree
public static ArithmeticTree createFormula(String s) {
var newObject = new ArithmeticTree();
newObject.formula = s;
newObject.parseFormulaToTree();
return newObject;
}
// serializes tree into a string
public String serialize() {
return preOrderToString(root);
}
// defines a variable "var" with value "val"
public void define(String var, double val) {
if (variables.containsKey(var)) {
variables.replace(var, val);
} else {
variables.put(var, val);
}
}
// evaluates the tree
public double evaluate() throws ScriptException {
var inOrderFormula = inOrderToString(root);
for (Map.Entry<String, Double> entry : variables.entrySet()) {
inOrderFormula = inOrderFormula.replace(entry.getKey(), entry.getValue().toString());
}
var factory = new ScriptEngineManager();
var engine = factory.getEngineByName("JavaScript");
var obj = engine.eval(inOrderFormula);
return Double.parseDouble(obj.toString());
}
private void parseFormulaToTree() {
String[] elements = formula.split(" ");
root = new Node(elements[0]);
Stack<Node> stack = new Stack<>();
stack.push(root);
Node nodeElement;
Node top;
for (int i = 1; i < elements.length; i++) {
nodeElement = new Node(elements[i]);
top = stack.lastElement();
if (top.isOperator()) {
if (top.left == null) top.left = nodeElement;
else top.right = nodeElement;
if (nodeElement.isOperator()) stack.push(nodeElement);
}
while (!stack.isEmpty() && stack.lastElement().right != null) {
stack.pop();
}
}
}
private String preOrderToString(Node node) {
if (node == null) return "";
var string = "";
string += node.content;
if (node.left != null) string += " " + preOrderToString(node.left);
if (node.right != null) string += " " + preOrderToString(node.right);
return string;
}
private String inOrderToString(Node node) {
if (node == null) return "";
var string = "";
if (node.left != null) string += inOrderToString(node.left) + " ";
string += node.content;
if (node.right != null) string += " " + inOrderToString(node.right);
return string;
}
}