Created
February 11, 2019 22:49
-
-
Save jonbodner/ad334f9eb98e89da3da13128ffd2d985 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
package com.example.demo.calculator; | |
import java.util.ArrayDeque; | |
import java.util.Deque; | |
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())) { | |
String op = operators.pop(); | |
double second = numbers.pop(); | |
double first = numbers.pop(); | |
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); | |
} | |
numbers.push(result); | |
} | |
operators.push(token); | |
break; | |
case "(": | |
operators.push(token); | |
break; | |
case ")": | |
for (String op = operators.peekFirst(); !op.equals("("); op = operators.peekFirst()) { | |
operators.pop(); | |
double second = numbers.pop(); | |
double first = numbers.pop(); | |
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); | |
} | |
numbers.push(result); | |
} | |
operators.pop(); | |
break; | |
default: | |
double d = Double.parseDouble(token); | |
numbers.push(d); | |
break; | |
} | |
} | |
for (String op = operators.peekFirst(); op != null; op = operators.peekFirst()) { | |
operators.pop(); | |
double second = numbers.pop(); | |
double first = numbers.pop(); | |
double result = 0; | |
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); | |
} | |
numbers.push(result); | |
} | |
} 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 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