I am sure this is becoming waaaay more complicated than it should be. I have tweaked it again, as I found a few cases that didn't work. Now I still can't pass it, but I have no clue where to look for next?
package com.codegym.task.task34.task3404;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/*
Recursion for mathematical expressions
*/
public class Solution {
public static void main(String[] args) {
Solution solution = new Solution();//
solution.recurse( "3-1+5", 0);
solution.recurse("sin(2*(-5+1.5*4)+28)", 0); // Expected output: 0.5 6
solution.recurse("tan(2025 ^ 0.5)", 0); // Expected output: 1 2
solution.recurse("1+2.41+1", 0); // Expected 4.41 2
solution.recurse("2^2", 0); // Expected 4 1
solution.recurse(" 3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3", 0); //Expected 3 6
}
public void recurse(final String expression, int countOperation) {
//implement
String currentExpression = expression;
if (countOperation == 0) {
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) {
String sum = expression.replaceAll(" ", "");
while (sum.contains("^") || sum.contains("*") || sum.contains("/") || sum.contains("+") || sum.contains("-") && !sum.startsWith("-")) {
if (sum.contains("^")) {
int index = sum.indexOf("^");
double[] aIndex = findA(sum, index);
double[] bIndex = findB(sum, index);
double answer = Math.pow(aIndex[0], bIndex[0]);
sum = sum.substring(0, (int) aIndex[1]) + answer + sum.substring((int) bIndex[1]);
} else if (sum.contains("*")) {
int index = sum.indexOf("*");
double[] aIndex = findA(sum, index);
double[] bIndex = findB(sum, index);
double answer = aIndex[0] * bIndex[0];
sum = sum.substring(0, (int) aIndex[1]) + answer + sum.substring((int) bIndex[1]);
} else if (sum.contains("/")) {
int index = sum.indexOf("/");
double[] aIndex = findA(sum, index);
double[] bIndex = findB(sum, index);
double answer = aIndex[0] / bIndex[0];
sum = sum.substring(0, (int) aIndex[1]) + answer + sum.substring((int) bIndex[1]);
}else if (sum.contains("+") && sum.contains("-") && sum.indexOf("-") > 0) {
boolean posFirst = sum.indexOf("+") < sum.indexOf("-");
if (posFirst) {
int index = sum.indexOf("+");
double[] aIndex = findA(sum, index);
double[] bIndex = findB(sum, index);
double answer = aIndex[0] + bIndex[0];
sum = sum.substring(0, (int) aIndex[1]) + answer + sum.substring((int) bIndex[1]);
}else {
int index = sum.indexOf("-");
double[] aIndex = findA(sum, index);
double[] bIndex = findB(sum, index);
double answer = aIndex[0] - bIndex[0];
sum = sum.substring(0, (int) aIndex[1]) + answer + sum.substring((int) bIndex[1]);
}
}else if (sum.contains("+")) {
int index = sum.indexOf("+");
double[] aIndex = findA(sum, index);
double[] bIndex = findB(sum, index);
double answer = aIndex[0] + bIndex[0];
sum = sum.substring(0, (int) aIndex[1]) + answer + sum.substring((int) bIndex[1]);
} else if (sum.contains("-")) {
int index = sum.indexOf("-");
double[] aIndex = findA(sum, index);
double[] bIndex = findB(sum, index);
double answer = aIndex[0] - bIndex[0];
sum = sum.substring(0, (int) aIndex[1]) + answer + sum.substring((int) bIndex[1]);
}
}
return Double.parseDouble(sum);
}
private double[] findA(String sum, int index){
StringBuilder stringBuilder = new StringBuilder();
double[] a = new double[2];
for (int i = index-1; i >= 0; i--){
if (sum.charAt(i) == '^' || sum.charAt(i) == '*' || sum.charAt(i) == '/' || sum.charAt(i) == '+'){
a[1] = i+1;
break;
}
if (sum.charAt(i) == '-' && i != 0 && sum.charAt(i-1) != '^' && sum.charAt(i-1) != '*' && sum.charAt(i-1) != '/' && sum.charAt(i-1) != '+' && sum.charAt(i-1) != '-'){
a[1] = i+1;
break;
}
stringBuilder.insert(0, sum.charAt(i));
if (i == 0){
a[1] = i;
}
}
try{
a[0] = Double.parseDouble(stringBuilder.toString());
}catch (Exception e){
int x = Integer.parseInt(stringBuilder.toString());
a[0] = x * 1.0;
}
return a;
}
private double[] findB(String sum, int index){
StringBuilder stringBuilder = new StringBuilder();
double[] b = new double[2];
for (int i = index+1; i < sum.length(); i++){
if (sum.charAt(i) == '^' || sum.charAt(i) == '*' || sum.charAt(i) == '/' || sum.charAt(i) == '+' || sum.charAt(i) == '-' && i != index+1){
b[1] = i;
break;
}
stringBuilder.append(sum.charAt(i));
if (i == sum.length()-1){
b[1] = i+1;
}
}
try{
b[0] = Double.parseDouble(stringBuilder.toString());
}catch (Exception e){
int x = Integer.parseInt(stringBuilder.toString());
b[0] = x * 1.0;
}
return b;
}
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;
}
char prev = '.';
for (char x : expression.toCharArray()){
if (x == prev){
if (x == '-'){
operationsCount--;
}
}
prev = x;
}
return operationsCount;
}
}