-
-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathMathExpressionManager.java
More file actions
344 lines (301 loc) · 11 KB
/
MathExpressionManager.java
File metadata and controls
344 lines (301 loc) · 11 KB
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package util;
import parser.CustomScanner;
import parser.Function;
import parser.MathExpression;
import parser.STRING;
import parser.TYPE;
import java.util.ArrayList;
import java.util.InputMismatchException;
import java.util.List;
/**
* Objects of this class attempt to optimize and then evaluate a math
* expression. If the expression's MathExpression object is present in the
* functions database (actually an ArrayList of MathExpression objects)
* then it just retrieves the scanned and validated code
* and solves it. Else,it must go through all the steps and then solve it.
* This happens when:
* 1. The expression is a new one.
* 2. The expression has been computed before but
* to limit memory usage, it has been deleted from memory.
* @author GBEMIRO
*/
public class MathExpressionManager {
private ArrayList<MathExpression> functions=new ArrayList<>();
/**
* Determines the maximum number of MathExpression objects that objects
* of this class use to optimize an evaluation of an expression.
*/
private int maxSize=200;
public MathExpressionManager() {
storeFunction(new MathExpression("1+1"));
}
/**
*
* @return all function objects stored by this MathExpressionManager object
*/
public ArrayList<MathExpression> getFunctions() {
return functions;
}
/**
*
* @param functions the store of MathExpression objects that this MathExpressionManager object will store
*/
public void setFunctions(ArrayList<MathExpression> functions) {
this.functions = functions;
}
public int getMaxSize() {
return maxSize;
}
public void setMaxSize(int maxSize) {
this.maxSize = maxSize;
}
/**
* A workspace uses a MathExpressionManager to
* manage and optimize functions used in calculations.
* Each of these functions have different VariableManager
* objects but all these objects are actually accessing, storing
* creating and modifying their variables and constants from one
* single Variable database( actually an ArrayList of Variable objects ) in the program.
* This method hence allows an object of this class to return a reference to any of
* the VariableManager objects associated with the MathExpression objects it manages,since it
* knows that the destination database(ArrayList) is the same,i.e all the MathExpression objects
* are only accessing the same set and copy of variables and constants.
* @return the VariableManager object associated with the first MathExpression
* object stored by objects of this class.
*/
public VariableManager getVariableManager(){
if(functions.size()>0){
return functions.get( 0 ).getVariableManager();
}
else{
throw new NullPointerException("No function created yet!");
}
}
/**
* checks if the MathExpression object passed to it as an argument can be optimized or not
* @param expression: The expression to evaluate
* @return true if the MathExpression is optimizable
*/
public boolean canOptimizeFunction(String expression){
return getFunctionByExpression(expression)!=null;
}
/**
* stores a MathExpression in objects of this class.
* The storage is done in such a way that the object is inserted
* from the front.
* @param function the new MathExpression to store
*/
public void storeFunction(MathExpression function){
if(!contains(function) && function.isCorrectFunction()){
functions.add(function);
int sz;
while( (sz=functions.size()) >= maxSize){
functions.remove(sz-1);
}
}
}
/**
*
* @param func the MathExpression object to search for
* @return true if the MathExpression object is found
*/
public boolean contains(MathExpression func){
return getFunctionByExpression(func.getExpression())!=null;
}//end method
public MathExpression getFunction(MathExpression function){
return functions.get(functions.indexOf(function));
}
/**
*
* @param index the location from which we wish to retrieve the MathExpression object
* @return the MathExpression object stored at the specified index.
*/
public MathExpression getFunctionAt(int index){
if(index>=0&&index<functions.size()){
return functions.get(index);
}
else{
throw new ArrayIndexOutOfBoundsException("Function Store Access Error");
}
}//end method getFunctionAt
/**
*
* @param expression the String representation of the MathExpression object
* @return the MathExpression object in the store that goes by that name or null if none is found.
* @throws NullPointerException
*/
public MathExpression getFunctionByExpression(String expression) throws NullPointerException{
int size=functions.size();
String expr = STRING.purifier(expression);
for(int i=0;i<size;i++){
String checkExpr = STRING.purifier( functions.get(i).getExpression() );
if(expr.equals(checkExpr)){
return functions.get(i);
}
}//end for
return null;
}//end method getFunctionByName
/**
*
* @param scanner the scanner object to search for in the store
* @return the MathExpression object in the store that possesses that scanned form
*/
public MathExpression getFunctionByScanner(ArrayList<String>scanner){
int size=functions.size();
for(int i=0;i<size;i++){
if(functions.get(i).getScanner()==scanner){
return functions.get(i);
}
}//end for
return null;
}
/**
* removes the MathExpression object at the specified location
* @param index the location from which the MathExpression is to be removed
*/
public void removeFunctionAt(int index){
if(contains(functions.get(index))){
functions.remove(index);
}
}
/**
* Removes the MathExpression object in the store that goes by that name
* @param funcName the String representation of the MathExpression object
*/
public void removeFunctionByName(String funcName){
int size=functions.size();
for(int i=0;i<size;i++){
if(functions.get(i).getExpression().equals(funcName)){
functions.remove(i);
}//end if
}//end for
}//end method removeFunctionByName
/**
*removes the MathExpression object that has that scanner
* @param scanner the scanner object to search for in the store
*/
public void removeFunctionByScanner(ArrayList<String>scanner){
int size=functions.size();
for(int i=0;i<size;i++){
if(functions.get(i).getScanner()==scanner){
functions.remove(i);
}
}//end for
}//end method removeFunctionByScanner
/**
*
* @param name the name or String format of the MathExpression object to be optimized
* @return the optimized MathExpression object such that it is given its attributes already processed and ready for use
*/
public MathExpression optimizeFunction(String name){
return getFunctionByExpression(name);
}
/**
*
* @return true if this object has no
* MathExpression objects to manage.
*/
public boolean isEmpty(){
return functions.isEmpty()||this==null;
}
/**
*
* @param expr The expression to be evaluated
* by the MathExpression to be created.
*/
public MathExpression createFunction( String expr ){
MathExpression f = new MathExpression(expr);
storeFunction( f );
return f;
}//end method createFunction
/**
* Takes a math expression,
* optimizes it if possible,
* and then solves it.
* Else if the expression cannot be optimized,
* it has to interpret and then evaluate it.
* It then stores the expression.
* @param expr The expression to evaluate.
* @param clazz The java.util.Class that the parent MathExpression belongs to.. may be MathExpression.class, BigMathExpression.class etc.
* @return the result.
*/
public <T extends MathExpression> String solve(String expr, Class<T> clazz) throws NullPointerException{
try {
CustomScanner cs = new CustomScanner( STRING.purifier(expr), false, VariableManager.endOfLine);
List<String> scanned = cs.scan();
String mathExpr = null;
int exprCount = 0;
for(String code : scanned) {
if(code.contains("=")){
boolean success = Function.assignObject(code+";", clazz);
if(!success) {
throw new Exception("Bad Variable or Function assignment!");
}
}
else{
mathExpr = code;
++exprCount;
}
}
MathExpression f = null;
if (mathExpr!=null && !mathExpr.isEmpty() && exprCount == 1) {
if ((f = getFunctionByExpression(mathExpr)) != null) {//optimize function
}//end if
else {
/**
* can take care of the raw input
* since it will still scan for variables and
* constants in the constructor
*/
f = new MathExpression("("+mathExpr+")");
storeFunction(f);
}//end else
}//end if
if (f != null) {
return analyzeSolution(f);
} else {
return "0";//variable or function init or update
}
}
catch(Exception e){
e.printStackTrace();
return "Syntax Error!";
}
}//end method
public static String analyzeSolution(MathExpression expr){
TYPE type;
try {
String val = expr.solve();
type = expr.getReturnType();
if(val.contains(",")|| val.contains("%")){
return val;
}
for(int i=0;i<val.length();i++){
String token = val.substring(i,i+1);
if(STRING.isNumberComponent(token)){
break;
}
}
if(type == TYPE.MATRIX){
return val;
}
double v = Double.parseDouble(val);//test to see that a valid number was returned
return val;
}
catch(Exception e){e.printStackTrace();
if(e instanceof NumberFormatException || e instanceof InputMismatchException){
return "Syntax Error!";
}
else if(e instanceof ArithmeticException){
return "Valid Range Error";
}
else{
return "Math Input Error";
}
}
}
}//end class MathExpressionManager