Вычисляет все правильно (во всяком случае все приведенные примеры), рекурсию использую.
Подскажите, где и что я не учла.
package com.javarush.task.task34.task3404;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*
Рекурсия для мат. выражения
*/
public class Solution {
public static void main(String[] args) {
Solution solution = new Solution();
solution.recurse("cos(3 + 19*3)", 0); //expected output 0.5 6
// sin( 2 * ( -5 + 1.5 * 4) + 28 )
}
public boolean isNum(String exp) {
return exp.matches("^\\d+(\\.\\d+)?");
}
public void recurse(final String expression, int countOperation) {
double decision = 0.0;
String expressionTrim = expression.replaceAll("\\s", "");
System.out.println("expressionTrim = " + expressionTrim);
// проверяем, является ли выражение числом и выводим результат
if (isNum(expressionTrim)) {
NumberFormat nf = new DecimalFormat("#.##");
System.out.printf("%s %d%n", nf.format(Double.parseDouble(expressionTrim)),countOperation);
}
// проверяем на паттерн - sin30.0 и подобное
else if (expressionTrim.matches("[a-z]{3}+[\\.0-9]+")) {
countOperation++;
// вычисляем функцию и производим действие
String function = expressionTrim.substring(0, 3);
double degree = Double.parseDouble(expressionTrim.substring(function.length()));
switch (function) {
case "sin":
decision = Math.sin(Math.toRadians(degree));
break;
case "cos":
decision = Math.cos(Math.toRadians(degree));
break;
case "tan":
decision = Math.tan(Math.toRadians(degree));
break;
}
System.out.println("decision = " + decision);
recurse(Double.toString(decision), countOperation);
}
// в иных случаях
else {
// вычисляем выражение до последней открытой скобки "sin(2*"
String partOne = expressionTrim.substring(0, expressionTrim.lastIndexOf("("));
// вычисляем выражение до первой закрытой скобки "+28)"
String partTwo = expressionTrim.substring(expressionTrim.indexOf(")") + 1);
System.out.println("partOne = " + partOne);
System.out.println("partTwo = " + partTwo);
// вычисляем выражение в средних скобках "-5+1.5*4"
String inBrackets = expressionTrim.substring(expressionTrim.lastIndexOf("(") +1, expressionTrim.indexOf(")"));
// вычисляем количество операций в выражении
Pattern pattern = Pattern.compile("[-+*^]|[a-z]{3}");
Matcher matcher = pattern.matcher(inBrackets);
while (matcher.find()) {
countOperation++;
}
System.out.println("inBrackets = " + inBrackets);
// создаем массив цифр из выражения в скобках
String[] numbers = inBrackets.split("[-+*^]");
// если перед первым числом стоит -, то в массив первым элементом будет ""
if (numbers[0].equals("")) numbers[0] = "0";
// создаем массив операций "-+*^"
String[] signs = inBrackets.split("(\\d\\.\\d)+|[0-9]+");
// если первым элементом в выражении стоит число, то в массив первым элементом будет ""
System.out.println("numbers = " + Arrays.toString(numbers));
System.out.println("signs = " + Arrays.toString(signs));
// копируем массив цифр в лист
List<String> numbersList = new ArrayList<>(Arrays.asList(numbers));
// создаем лист для операций
List<String> signsList = new ArrayList<>();
// добавляем в лист только непустые элементы
for (String s: signs) {
if (!s.equals("")) {
signsList.add(s);
}
}
System.out.println("numbersList = " + numbersList);
System.out.println("signsList = " + signsList);
// находим индексы каждого вида операции в листе операций (если такой операции в листе нет, останется -1)
int indexMult = -1;
int indexSqr = -1;
int indexPlus = -1;
int indexMinus = -1;
if (signsList.contains("*")) indexMult = signsList.indexOf("*");
if (signsList.contains("+")) indexPlus = signsList.indexOf("+");
if (signsList.contains("-")) indexMinus = signsList.indexOf("-");
if (signsList.contains("^")) indexSqr = signsList.indexOf("^");
double one = 0;
System.out.println("indexMult = " + indexMult);
// если в выражении есть операция умножение "*"
if (indexMult >= 0) {
// по индексу операции находим в листе чисел два числа с таким же индексом и следующим и производим операцию
one = Double.parseDouble(numbersList.get(indexMult)) * Double.parseDouble(numbersList.get(indexMult+1));
// результат операции записываем в лист чисел вместо первого числа
numbersList.set(indexMult, String.valueOf(one));
// второе число обнуляем в листе чисел
numbersList.set(indexMult+1, "0");
System.out.println("numbersList = " + numbersList);
}
System.out.println("one = " + one);
double two = 0;
System.out.println("indexSqr = " + indexSqr);
// если в выражении есть операция вычисления квадрата или корня "^"
if (indexSqr >= 0) {
// по индексу операции находим в листе чисел два числа с таким же индексом и следующим и производим операцию
two = Math.pow(Double.parseDouble(numbersList.get(indexSqr)), Double.parseDouble(numbersList.get(indexSqr+1)));
// результат операции записываем в лист чисел вместо первого числа
numbersList.set(indexSqr, String.valueOf(two));
// второе число обнуляем в листе чисел
numbersList.set(indexSqr+1, "0");
System.out.println("numbersList = " + numbersList);
}
System.out.println("two = " + two);
double three = 0;
System.out.println("indexMinus = " + indexMinus);
// если в выражении есть операция вычитания "-"
if (indexMinus >= 0) {
// по индексу операции находим в листе чисел два числа с таким же индексом и следующим и производим операцию
three = Double.parseDouble(numbersList.get(indexMinus)) - Double.parseDouble(numbersList.get(indexMinus+1));
// результат операции записываем в лист чисел вместо первого числа
numbersList.set(indexMinus, String.valueOf(three));
// второе число обнуляем в листе чисел
numbersList.set(indexMinus+1, "0");
System.out.println("numbersList = " + numbersList);
}
System.out.println("three = " + three);
double four = 0;
System.out.println("indexPlus = " + indexPlus);
// если в выражении есть операция сложения "+"
if (indexPlus >= 0) {
// по индексу операции находим в листе чисел два числа с таким же индексом и следующим и производим операцию
four = Double.parseDouble(numbersList.get(indexPlus)) + Double.parseDouble(numbersList.get(indexPlus+1));
numbersList.set(indexPlus, String.valueOf(four));
// второе число обнуляем в листе чисел
numbersList.set(indexPlus+1, "0");
System.out.println("numbersList = " + numbersList);
}
System.out.println("four = " + four);
// суммируем все элементы в листе
double result = numbersList.stream()
.mapToDouble(Double::parseDouble)
.sum();
// составляем новое выражение, шде центральную часть заменяем числом, которое мы вычислили
String newExpression = partOne + result + partTwo;
System.out.println("newExpression = " + newExpression);
// вызываем рекурсивно метод с новым выражение и посчитанным количеством операций в этом разборе
recurse(newExpression, countOperation);
}
//implement
}
public Solution() {
//don't delete
}
}