package com.coding.basic.stack.expr;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import javafx.util.converter.NumberStringConverter;
public class InfixExpr {
String expr = null;
Map<Character, Integer> priorityMap = null;
List<String> exprTokens = null;
public InfixExpr(String expr) {
priorityMap = new HashMap<Character, Integer>();
init();
this.expr = expr;
exprTokens = parse();
}
public void init(){
priorityMap.put('+', 0);
priorityMap.put('-', 0);
priorityMap.put('*', 1);
priorityMap.put('/', 1);
}
public float evaluate() {
Stack<Character> operatorStack = new Stack<>();
Stack<Float> operandStack = new Stack<>();
Float operandOne, operandTwo;
int index = 0;
while(index < exprTokens.size()){
String cc = exprTokens.get(index);
try{
if(isFloat(cc)){
System.out.println("push operand: " + cc);
operandStack.push(Float.parseFloat(cc));
System.out.println("peek: " + operandStack.peek());
}
else if(priorityMap.get(cc.charAt(0)) != null){
char c = cc.charAt(0);
if(operatorStack.isEmpty()){
System.out.println("push operator: " + cc);
operatorStack.push(c);
}
else{
int preOperatorPriority = getPriority(operatorStack.peek());
int curOperatorPriority = getPriority(c);
if(curOperatorPriority <= preOperatorPriority){
//do precalculation first
operandTwo = operandStack.pop();
operandOne = operandStack.pop();
char operator = operatorStack.pop();
float result = doCalculation(operandOne, operandTwo, operator);
operandStack.push(result);
operatorStack.push(c);
}
else{
System.out.println("push operator: " + cc);
operatorStack.push(c);
}
}
}
else{
throw new Exception("Unsupported character: " + cc);
}
}
catch(Exception e){
e.printStackTrace();
}
index ++;
}
System.out.println("dumpping operator stack:");
dumpStack(operatorStack);
System.out.println("dumpping operand stack:");
dumpStack(operandStack);
try{
while(!operatorStack.isEmpty()){
operandTwo = operandStack.pop();
operandOne = operandStack.pop();
char operator = operatorStack.pop();
float result = doCalculation(operandOne, operandTwo, operator);
operandStack.push(result);
}
}catch(Exception e){
e.printStackTrace();
}
if(operandStack.size() > 1){
System.err.println("More than one result reminded in operands stack.");
}
return operandStack.pop();
}
private float doCalculation(float operandOne, float operandTwo, char operator) throws Exception{
System.out.println("operand 1: " + operandOne + " operand 2: " + operandTwo + " operator: " + operator);
float result = 0f;
if(operator == '+'){
result = operandOne + operandTwo;
}
else if(operator == '-'){
result = operandOne - operandTwo;
}
else if(operator == '*'){
result = operandOne * operandTwo;
}
else if(operator == '/'){
result = operandOne / operandTwo;
}
else{
throw new Exception("Unsupported operator");
}
System.out.println("result: " + result);
return result;
}
private int getPriority(Character c){
return priorityMap.get(c);
}
private boolean isFloat(String v){
try{
Float.parseFloat(v);
return true;
}
catch(Exception e){
return false;
}
}
private List<String> parse(){
List<String> vals = new ArrayList<>();
int p1 = 0;
int p2 = 1;
while(p2<expr.length()){
char c1 = expr.charAt(p1);
char c2 = expr.charAt(p2);
if(! Character.isDigit(c2)){
//current is operator
vals.add(expr.substring(p1,p2));
vals.add(String.valueOf(c2));
p2++;
p1 = p2;
}
else{
p2++;
}
}
if(p1<expr.length()){
//System.out.println("p1 = " + p1 + " char = " + expr.charAt(p1));
vals.add(expr.substring(p1));
}
dumpArray(vals);
return vals;
}
private void dumpArray(List<String> l){
for(int i =0; i<l.size(); i++){
System.out.print(l.get(i) + " ");
}
System.out.println();
}
private void dumpStack(Stack s){
Iterator itr = s.iterator();
while(itr.hasNext()){
System.out.print(itr.next()+" ");
}
System.out.println();
}
}