Считает и выводит правильно. Рекурсия присутствует. Чего не хватает? 🤢
![]()

package com.javarush.task.task34.task3404;
/*
Рекурсия для мат. выражения
*/
import java.text.DecimalFormat;
public class Solution {
public static void main(String[] args) {
Solution solution = new Solution();
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
}
public void recurse(final String expression, int countOperation) {
//implement
int count = countOperation;
//Убираем пробелы из строки
String exprWisoutGaps = expression.replaceAll(" ", "");
//разделяем пробелами операции и значения
String str = exprWisoutGaps.replaceAll("\\^", " ^ ");
str = str.replaceAll("\\(", " ( ");
str = str.replaceAll("\\)", " ) ");
str = str.replaceAll("\\*", " * ");
str = str.replaceAll("/", " / ");
str = str.replaceAll("\\+", " + ");
str = str.replaceAll("-", " - ");
str = str.replaceAll(" ", " ");
str = str.replaceAll("\\( - ", "\\( -"); //минус может встречаться просто для обозначения знака числа
//Создаём массив строк для операций, скобок и значений
String[] strArr = str.split(" ");
//Подкручиваем счётчик операций для случаев когда минус в исходной строке обозначает знак числа а не операцию
if (count == 0) {
for (int i = 0; i < strArr.length; i++) {
if (strArr[i].contains("-") && (i == 0 || strArr[i-1].contains("("))) count++;
}
}
//Если массив состоит из одной позиции, значит мы вычислили нужный нам результат
if (strArr.length == 1 || (strArr.length == 2 && strArr[0].equals("-"))) {
double res;
if (strArr.length == 1) res = Double.parseDouble(strArr[0]);
else res = 0.0 - Double.parseDouble(strArr[1]);
//подгоняем вывод
DecimalFormat decimalFormat = new DecimalFormat("#.##");
String sr = decimalFormat.format(res);
sr = sr.replaceAll(",", ".");
//выводим результат
System.out.println(sr + " " + countOperation);
return;
}
//Находим операцию, которую надо выполнить первой, заменяем в строке операцию на результат, увеличиваем счётчик, вызываем рекурсию
//позиции в массиве, среди которых ищем операцию для выполнения
int startPosition = 0;
int endPosition = strArr.length - 1;
//заходим внутрь самых вложенных скобок
for (int i = 0; i < strArr.length; i++) {
if (strArr[i].equals("(")) startPosition = i;
}
for (int i = startPosition; i <= endPosition; i++) {
if (strArr[i].equals(")")) {
endPosition = i;
break;
}
}
//находим операцию для вычисления по порядку: возведение в степень, умножение-деление, сложение-вычитание,
//если предыдущая позиция открывающая скобка, а следующая закрывающая скобка переходим к действию перед скобкой
int operationPosition = -1; //ищем возведение в степень
for (int i = startPosition; i <= endPosition; i++) {
if (strArr[i].equals("^")) {
operationPosition = i;
break;
}
}
if (operationPosition == -1) { //если не нашли возведение в степень, ищем умножение-деление
for (int i = startPosition; i <= endPosition; i++) {
if (strArr[i].equals("*") || strArr[i].equals("/")) {
operationPosition = i;
break;
}
}
}
if (operationPosition == -1) { //если не нашли умножение-деление, ищем сложение-вычитание
for (int i = startPosition; i <= endPosition; i++) {
if (strArr[i].equals("+") || strArr[i].equals("-")) {
operationPosition = i;
break;
}
}
}
if (operationPosition == -1 && (endPosition - startPosition) == 2) { //если не нашли арифметических действий, значит действие за скобкой
strArr[startPosition] = null; //обнуляем скобки
strArr[endPosition] = null;
if (strArr[startPosition-1].equals("sin") || strArr[startPosition-1].equals("cos") || strArr[startPosition-1].equals("tan")) {
operationPosition = startPosition - 1; //если перед скобкой стоял синус, косинус или тангенс, будем вычислять
}
}
// System.out.println(" ! " + strArr[operationPosition]);
//производим вычисления, обнуляем ячейки со значениями над которыми производили вычисления,
//в ячейки с операциями записываем результат
double result = 0;
if (operationPosition > -1) {
switch (strArr[operationPosition]) {
case ("sin") :
result = Math.sin(Math.toRadians(Double.parseDouble(strArr[operationPosition + 2])));
strArr[operationPosition + 2] = null;
break;
case ("cos") :
result = Math.cos(Math.toRadians(Double.parseDouble(strArr[operationPosition + 2])));
strArr[operationPosition + 2] = null;
break;
case ("tan") :
result = Math.tan(Math.toRadians(Double.parseDouble(strArr[operationPosition + 2])));
strArr[operationPosition + 2] = null;
break;
case ("^") :
result = Math.pow(Double.parseDouble(strArr[operationPosition - 1]), Double.parseDouble(strArr[operationPosition + 1]));
strArr[operationPosition - 1] = null;
strArr[operationPosition + 1] = null;
break;
case ("*") :
result = Double.parseDouble(strArr[operationPosition - 1]) * Double.parseDouble(strArr[operationPosition + 1]);
strArr[operationPosition - 1] = null;
strArr[operationPosition + 1] = null;
break;
case ("/") :
result = Double.parseDouble(strArr[operationPosition - 1]) / Double.parseDouble(strArr[operationPosition + 1]);
strArr[operationPosition - 1] = null;
strArr[operationPosition + 1] = null;
break;
case ("+") :
result = Double.parseDouble(strArr[operationPosition - 1]) + Double.parseDouble(strArr[operationPosition + 1]);
strArr[operationPosition - 1] = null;
strArr[operationPosition + 1] = null;
break;
case ("-") : //минус может встречаться просто для обозначения знака числа
double value;
try {
value = Double.parseDouble(strArr[operationPosition - 1]);
result = value - Double.parseDouble(strArr[operationPosition + 1]);
strArr[operationPosition - 1] = null;
} catch (NumberFormatException nfe) {
result = 0.0 - Double.parseDouble(strArr[operationPosition + 1]);
}
strArr[operationPosition + 1] = null;
break;
}
strArr[operationPosition] = String.valueOf(result); //записываем результат
count++; //увеличиваем счётчик операций
}
// System.out.println(strArr[operationPosition]);
//обновляем строку
StringBuilder sb = new StringBuilder("");
for (int i = 0; i < strArr.length; i++) {
if (strArr[i] != null) sb.append(strArr[i]);
}
//вызываем рекурсию
recurse(sb.toString(), count);
}
public Solution() {
//don't delete
}
}
// На вход подается строка - математическое выражение.
// Выражение включает целые и дробные числа, скобки (), пробелы, знак отрицания -, возведение в степень ^, sin(x), cos(x), tan(x)
// Для sin(x), cos(x), tan(x) выражение внутри скобок считать градусами, например, cos(3 + 19*3)=0.5
// Степень задается так: a^(1+3) и так a^4, что эквивалентно a*a*a*a.
// С помощью рекурсии вычислить выражение и количество математических операций. Вывести через пробел результат в консоль.
// Результат выводить с точностью до двух знаков, для 0.33333 вывести 0.33, использовать стандартный принцип округления.
// Знак отрицания перед числом также считать математической операцией.
// Не создавай в классе Solution дополнительные поля.
// Не пиши косвенную рекурсию.
//
// Пример, состоящий из операций sin * - + * +:
// sin(2*(-5+1.5*4)+28)
// Результат:
// 0.5 6
//
// Пример, состоящий из операций tan ^:
// tan(2025 ^ 0.5)
// Результат:
// 1 2
//
//
// Требования:
// 1. В классе Solution не должны быть созданы дополнительные поля.
// 2. Метод recurse должен выводить на экран результат вычисления заданного выражения (пример в условии).
// 3. Метод recurse не должен быть статическим.
// 4. Метод recurse должен быть рекурсивным.