package com.coding.basic.stack.expr;
import com.coding.basic.stack.Stack;
import java.util.regex.Pattern;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
public class InfixExpr {
String expr = null;
Stack numStack = new Stack();
Stack opStack = new Stack();
private static final String REGEX_OPR = "[\\+\\-\\*\\/]";
public InfixExpr(String expr) {
this.expr = expr;
}
public float evaluate() {
processNumAndOperatorWithPriority();
while(!opStack.isEmpty()){
char op = (char)opStack.pop();
float num2 = (float)numStack.pop();
float num1 = (float)numStack.pop();
numStack.push(calculate(num1, op, num2));
}
return (float)numStack.pop();
}
private void processNumAndOperatorWithPriority() {
String[] numStrArr = this.getNumbers();
char[] operators = this.getOperators();
if(numStrArr.length!=operators.length+1){
throw new RuntimeException("Invalid Expression:"+this.expr);
}
this.numStack.push(Float.parseFloat(numStrArr[0]));
this.numStack.push(Float.parseFloat(numStrArr[1]));
this.opStack.push(operators[0]);
for(int i=2;i<numStrArr.length;i++){
char op = operators[i-1];
while(!this.opStack.isEmpty() && isLowerPriority(op)){
float num2 = (float)this.numStack.pop();
float num1 = (float)this.numStack.pop();
char prevOp = (char)this.opStack.pop();
this.numStack.push(this.calculate(num1, prevOp, num2));
}
this.opStack.push(op);
this.numStack.push(Float.parseFloat(numStrArr[i]));
}
}
private char[] getOperators(){
char[] charArr= this.expr.toCharArray();
char[] result = new char[charArr.length];
int count = 0;
for(char tmp:charArr){
if(tmp=='+'||tmp=='-'||tmp=='*'||tmp=='/'){
result[count]=tmp;
count++;
}else if(!Character.isDigit(tmp)){
throw new RuntimeException("Unsupported Operator:"+tmp);
}
}
return Arrays.copyOf(result, count);
}
private String[] getNumbers(){
return this.expr.split(REGEX_OPR);
}
private boolean isLowerPriority(char opr){
char prevOp = (char)this.opStack.peek();
boolean result = false;
if((prevOp=='*'||prevOp=='/')){
result = true;
}else if(opr=='+'||opr=='-'){
result = true;
}
return result;
}
private float calculate(float num1,char operator, float num2){
if(operator=='+'){
return num1+num2;
}else if(operator=='-'){
return num1-num2;
}else if(operator=='*'){
return num1*num2;
}else{
return num1/num2;
}
}
}