Created
February 25, 2019 20:14
-
-
Save jonbodner/1412a0d32b6050c2eec3f9755c64d56d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class CalculatorImpl implements Calculator { | |
public CalculatorImpl() { | |
} | |
@Override | |
public double process(String expression) { | |
String[] tokens = expression.split(" "); | |
Deque<String> operators = new ArrayDeque<>(); | |
Deque<Double> numbers = new ArrayDeque<>(); | |
try { | |
for (String token : tokens) { | |
switch (token) { | |
case "+": | |
case "-": | |
case "/": | |
case "*": | |
while (shouldEvaluate(token, operators.peekFirst())) { | |
evaluate(operators, numbers); | |
} | |
operators.push(token); | |
break; | |
case "(": | |
operators.push(token); | |
break; | |
case ")": | |
for (String op = operators.peekFirst(); !op.equals("("); op = operators.peekFirst()) { | |
evaluate(operators, numbers); | |
} | |
operators.pop(); | |
break; | |
default: | |
double d = Double.parseDouble(token); | |
numbers.push(d); | |
break; | |
} | |
} | |
for (String op = operators.peekFirst(); op != null; op = operators.peekFirst()) { | |
evaluate(operators, numbers); | |
} | |
} catch (Exception e) { | |
throw new CalculatorException("Invalid expression: " + expression, e); | |
} | |
double result = numbers.pop(); | |
if (numbers.size() > 0) { | |
throw new CalculatorException("Invalid expression: " + expression); | |
} | |
return result; | |
} | |
private void evaluate(Deque<String> operators, Deque<Double> numbers) { | |
String op = operators.pop(); | |
double second = numbers.pop(); | |
double first = numbers.pop(); | |
double result = getResult(op, second, first); | |
numbers.push(result); | |
} | |
private double getResult(String op, double second, double first) { | |
double result; | |
switch (op) { | |
case "+": | |
result = first + second; | |
break; | |
case "-": | |
result = first - second; | |
break; | |
case "*": | |
result = first * second; | |
break; | |
case "/": | |
result = first / second; | |
break; | |
default: | |
throw new CalculatorException("Unexpected operator " + op); | |
} | |
return result; | |
} | |
private boolean shouldEvaluate(String newOp, String topOp) { | |
if (topOp == null || topOp.equals("(")) { | |
return false; | |
} | |
// with 4 standard operators, the only time you don't evaluate is | |
// when the new operator is a * or / and the top operator is a + or - | |
// topOp newOp shouldEvaluate | |
// - - - - - - - - - - - - - | |
// +, - +, - true | |
// *, / +, - true | |
// +, - *, / false | |
// *, / *, / true | |
if ((topOp.equals("+") || topOp.equals("-")) && (newOp.equals("*") || newOp.equals("/"))) { | |
return false; | |
} | |
return true; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment