Or am I missed something?
package com.codegym.task.task34.task3404;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Solution {
public static void main(String[] args) {
Solution solution = new Solution();
solution.recurse("2^(1+3)", 0); //expected output 0.5 6
// String expression = "(1+2)*(3+4)";
// solution.recurse(expression, 0);
}
public void recurse(final String expression, int countOperation) {
//implement
String currentExpression = expression;
if (countOperation == 0) {
currentExpression = currentExpression.replaceAll(" ", "").replaceAll("\\(-", "(0-");
if (currentExpression.charAt(0) == '-' || currentExpression.charAt(0) == '+') currentExpression = "0" + currentExpression;
countOperation = getOperationsCount(expression);
}
if (isNumber(currentExpression)) {
NumberFormat numberFormat = new DecimalFormat("#.##");
Double result = Double.parseDouble(currentExpression);
System.out.println(String.format("%s %d", numberFormat.format(result), countOperation));
return;
} else if (currentExpression.contains("(")) {
int lastParenthStart = currentExpression.lastIndexOf("(");
int lastParenthEnd = currentExpression.indexOf(")", lastParenthStart);
String mostInnerExpr = currentExpression.substring(lastParenthStart + 1, lastParenthEnd);
String innerFunction = lastParenthStart > 2 ? expression.substring(lastParenthStart - 3, lastParenthStart) : "nop";
if (isNumber(mostInnerExpr)) {
double mostInnerResult = Double.parseDouble(mostInnerExpr);
switch (innerFunction) {
case "sin":
mostInnerResult = Math.sin(mostInnerResult * Math.PI / 180);
lastParenthStart -= 3;
break;
case "cos":
mostInnerResult = Math.cos(mostInnerResult * Math.PI / 180);
lastParenthStart -= 3;
break;
case "tan":
mostInnerResult = Math.tan(mostInnerResult * Math.PI / 180);
lastParenthStart -= 3;
break;
}
currentExpression = currentExpression.substring(0, lastParenthStart)
.concat(String.valueOf(mostInnerResult))
.concat(currentExpression.substring(lastParenthEnd + 1));
} else {
// Expression in innermost block
if (innerFunction.equalsIgnoreCase("sin") || innerFunction.equalsIgnoreCase("cos") || innerFunction.equalsIgnoreCase("tan")) {
currentExpression = currentExpression.substring(0, lastParenthStart + 1)
.concat(String.valueOf(calcExpression(mostInnerExpr)))
.concat(currentExpression.substring(lastParenthEnd));
} else {
currentExpression = currentExpression.substring(0, lastParenthStart)
.concat(String.valueOf(calcExpression(mostInnerExpr)))
.concat(currentExpression.substring(lastParenthEnd + 1));
}
}
} else {
currentExpression = String.valueOf(calcExpression(currentExpression));
}
recurse(currentExpression, countOperation);
}
private double calcExpression(String expression) {
List<String> operations = new ArrayList<>(Arrays.asList(expression.split("\\d+(\\.\\d+)?")));
List<String> operands = new ArrayList<>(Arrays.asList(expression.split("[\\+\\-\\*\\/\\^]")));
while (operations.size() > 1) {
if (operations.contains("^")) {
int operIndex = operations.indexOf("^");
execOperation(operations, operands, operIndex);
} else if (operations.contains("*") || operations.contains("/")) {
int operIndex = getMinIndex(operations.indexOf("*"), operations.indexOf("/"));
execOperation(operations, operands, operIndex);
} else if (operations.contains("+") || operations.contains("-")) {
int operIndex = getMinIndex(operations.indexOf("+"), operations.indexOf("-"));
execOperation(operations, operands, operIndex);
}
}
return Double.parseDouble(operands.get(0));
}
private int getMinIndex(int firstIndex, int secondIndex) {
if (firstIndex == -1)
return secondIndex;
else if (secondIndex == -1)
return firstIndex;
else
return firstIndex > secondIndex ? secondIndex : firstIndex;
}
private void execOperation(List<String> operations, List<String> operands, int operIndex) {
double operResult = doOperation(operations.get(operIndex), operands.get(operIndex - 1), operands.get(operIndex));
operations.remove(operIndex);
operands.remove(operIndex);
operands.remove(operIndex - 1);
operands.add(operIndex - 1, String.valueOf(operResult));
}
private double doOperation(String operation, String leftOperand, String rightOperand) {
switch (operation) {
case "^":
return Math.pow(Double.parseDouble(leftOperand), Double.parseDouble(rightOperand));
case "*":
return Double.parseDouble(leftOperand) * Double.parseDouble(rightOperand);
case "/":
return Double.parseDouble(leftOperand) / Double.parseDouble(rightOperand);
case "-":
return Double.parseDouble(leftOperand) - Double.parseDouble(rightOperand);
case "+":
return Double.parseDouble(leftOperand) + Double.parseDouble(rightOperand);
}
throw new ArithmeticException("Wrong operation: " + operation);
}
private boolean isNumber(String expression) {
if (expression == null) return false;
return expression.matches("^[+-]?\\d+(\\.\\d+)?");
}
public Solution() {
//don't delete
}
private int getOperationsCount(String expression) {
String[] operations = new String[] {"sin", "cos", "tan", "\\^", "\\+", "\\-", "\\*", "\\/"};
int operationsCount = 0;
for (String operation : operations) {
operationsCount += expression.split(operation).length - 1;
}
return operationsCount;
}
}