Почему не проходит решение?
package com.javarush.task.task34.task3404;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*
Рекурсия для мат. выражения
*/
/*
{"sin(2*(-5+1.5*4)+28)", "0.5 6"}, +
{"tan(2025 ^ 0.5)", "1 2"}, +
{"1+(1+(1+1)*(1+1))*(1+1)+1", "12 8"}, +
{"-2^(-2)", "-0.25 3"}, +
{"-(-2^(-2))+2+(-(-2^(-2)))", "2.5 10"}, +
{"(-2)*(-2)", "4 3"}, +
{"sin(-30)", "-0.5 2"}, +
{"cos(-30)", "0.87 2"}, +
{"tan(-30)", "-0.58 2"},
{"2+8*(9/4-1.5)^(1+1)", "6.48 6"},
{"tan(44+sin(89-cos(180)^2))", "1 6"}, не согласен
{"-cos(180)^2", "-1 3"},
{"0+0.304", "0.3 1"},
{"-0", "0 1"},
{"sin(3.14/2)^2 + cos(3.14/2)^2","1 7"},
{"sin(2*55) - 2*sin(55)*cos(55)","0 7"}
*/
public class Solution {
public Solution() {
//don't delete
}
public static void main(String[] args) {
Solution solution = new Solution();
String s;
s = "sin(2*55) - 2*sin(55)*cos(55)";
solution.recurse(s, 0);
}
public static void s(String m) {
if (false) {
System.out.println(m);
}
}
/*
Если можно что-то посчитать, то мы это считаем и пробрасываем выражение дальше.
Если считать уже ничего не надо, мы просто выводим резльутат на экран.
Глобальные тезисы:
- Избавляемся от пробелов
- В первую очередь всегда надо считать то, что в самых внутренних скобках
- Когда мы находимся внутри скобок надо взять максималную по проиоритету операцию (помним, что скобок нет)
- Мы вместо максималной по проиоритету операции вычисляем число и пробрасываем результат дальше
*/
public void recurse(final String expression, int countOperation) {
s("");
// System.out.println("Очередная итерация. Количество: " + countOperation + " Выражение: " + expression);
s("Очередная итерация. Количество: " + countOperation + " Выражение: " + expression);
// обяъявление всех переменных
final String simpleNumber = "[0-9]+[\\.]?[0-9]*";
String expressionWithoutBlanks = ""; // выражение без пробелов
String part1 = ""; // левая часть, которую не трограем
String part2 = ""; // в этой части что-то посчитаем
String part3 = ""; // правая часть, которую не трогаем
boolean partsComplete = false;
String part21 = ""; // Часть 2.1
String part22 = ""; // Часть 2.2
String part23 = ""; // Часть 2.3
boolean someCalculateComplete = false; // что-то подсчитали
String strResult = ""; // Результат промежуточного вычисления
int addMinusOperation = 0;
Pattern pattern;
Matcher matcher;
if (countOperation > 10) {
s("Переполнение");
return;
}
{
if (expression.matches("[\\(]?" + "[\\-]?" + "[\\+]?" + simpleNumber + "[\\)]?")) {
String result;
s("Пришло число, надо вывести на печать");
result = String.valueOf(Double.valueOf(expression));
// if (Double.valueOf(expression) < 0) countOperation++; // не канает из-за tan(-30) . должно быть 2 операции
if (result.endsWith(".0")) result = result.replace(".0", "");
System.out.println(result + " " + (countOperation));
return;
}
}
s("Будем избавляться от пробелов");
{
expressionWithoutBlanks = expression.replace(" ", "");
s("Выражение после удаления пробелов: " + expressionWithoutBlanks);
}
s("Будем избавляться от двойных минусов");
{
if (expressionWithoutBlanks.contains("--")) countOperation = countOperation + 2;
expressionWithoutBlanks = expressionWithoutBlanks.replace("--", "+");
s("Выражение после удаления двойных минусов: " + expressionWithoutBlanks);
}
s("Будем избавляться от двойных плюсов");
{
expressionWithoutBlanks = expressionWithoutBlanks.replace("++", "+");
s("Выражение после удаления двойных минусов: " + expressionWithoutBlanks);
}
s("Формирование трех частей (сначала проверка на тригонометрию)");
/*
Сформируем три части
Левая - не меняем
Центральная - опрокидываем дальше
Правая - не меняем
Затем среднюю часть реккурсивно прокидываем дальше с повышением счетчика вычислений
*/
{
s("Проверка на наличие просто тригонометрии для парсинга");
/*
В дальнейшем мы будем анализировать скобки и избавляться от них, но для начала надо избавиться от простой тригонометрии
*/
if (!partsComplete) {
s("Проверка синуса");
String regexSimpleSinus = "sin[\\(]" + "[\\-]?" + simpleNumber + "[\\)]";
pattern = Pattern.compile(regexSimpleSinus);
matcher = pattern.matcher(expressionWithoutBlanks);
if (matcher.find()) {
s("Найдета простая тригонометрия (синус)");
part1 = expressionWithoutBlanks.substring(0, matcher.start());
part2 = expressionWithoutBlanks.substring(matcher.start(), matcher.end());
part3 = expressionWithoutBlanks.substring(matcher.end());
partsComplete = true;
}
}
if (!partsComplete) {
s("Проверка косинуса");
String regexSimpleSinus = "cos[\\(]" + "[\\-]?" + simpleNumber + "[\\)]";
pattern = Pattern.compile(regexSimpleSinus);
matcher = pattern.matcher(expressionWithoutBlanks);
if (matcher.find()) {
s("Найдета простая тригонометрия (косинус)");
part1 = expressionWithoutBlanks.substring(0, matcher.start());
part2 = expressionWithoutBlanks.substring(matcher.start(), matcher.end());
part3 = expressionWithoutBlanks.substring(matcher.end());
partsComplete = true;
}
}
if (!partsComplete) {
s("Проверка тангенса");
String regexSimpleSinus = "tan[\\(]" + "[\\-]?" + simpleNumber + "[\\)]";
pattern = Pattern.compile(regexSimpleSinus);
matcher = pattern.matcher(expressionWithoutBlanks);
if (matcher.find()) {
s("Найдета простая тригонометрия (тангенс)");
part1 = expressionWithoutBlanks.substring(0, matcher.start());
part2 = expressionWithoutBlanks.substring(matcher.start(), matcher.end());
part3 = expressionWithoutBlanks.substring(matcher.end());
partsComplete = true;
}
}
if (!partsComplete) {
s("Просто поиск скобок");
if (expressionWithoutBlanks.matches(".*[\\(].*")) {
int start = 0;
int end = 0;
s("Начинаем искать индексы скобок");
for (int i = 0; i < expressionWithoutBlanks.length() ; i++) {
if (expressionWithoutBlanks.charAt(i) == '(') start = i;
if (expressionWithoutBlanks.charAt(i) == ')') {
end = i;
break;
}
}
s("Найденные индексы: " + start + " " + end);
part1 = expressionWithoutBlanks.substring(0, start + 1);
part2 = expressionWithoutBlanks.substring(start + 1, end);
part3 = expressionWithoutBlanks.substring(end);
} else {
part1 = "";
part2 = expressionWithoutBlanks;
part3 = "";
}
}
// s("Формируем три части для работы");
}
s("СФОРМИРОВАНЫ ТРИ ЧАСТИ ДЛЯ ДАЙЛЬНЕЙШИХ ВЫЧИСЛЕНИЙ!");
s("Часть 1: " + part1);
s("Часть 2: " + part2);
s("Часть 3: " + part3);
s("Вычисление простой тригонометрии по средней части: синус, косинус, тангенс (должно идти до ликвидации скобок)");
{
// это простой синус
if (!someCalculateComplete) {
String regexSimpleSinus = "sin[\\(]" + "[\\-]?" + simpleNumber + "[\\)]";
pattern = Pattern.compile(regexSimpleSinus);
matcher = pattern.matcher(part2);
if (matcher.find()) {
if (part2.indexOf("-") > 0) addMinusOperation++;
Double r = Math.sin(Math.toRadians(Double.valueOf(part2.replace("sin(", "").replace(")", ""))));
strResult = String.format("%.2f", r).replace(",", ".");
part21 = "";
part22 = strResult;
part23 = "";
someCalculateComplete = true;
}
}
// это простой косинус
if (!someCalculateComplete) {
String regexSimpleCosinus = "cos[\\(]" + "[\\-]?" + simpleNumber + "[\\)]";
pattern = Pattern.compile(regexSimpleCosinus);
matcher = pattern.matcher(part2);
if (matcher.find()) {
s("СЕЙЧАС БУДЕТ ВЫЧИСЛЕНИЕ ПРОСТОГО КОСИНУСА");
if (part2.indexOf("-") > 0) addMinusOperation++;
Double r = Math.cos(Math.toRadians(Double.valueOf(part2.replace("cos(", "").replace(")", ""))));
strResult = String.format("%.2f", r).replace(",", ".");
part21 = "";
part22 = strResult;
part23 = "";
someCalculateComplete = true;
}
}
// это простой тангенс
if (!someCalculateComplete) {
String regexSimpleTan = "tan[\\(]" + "[\\-]?" + simpleNumber + "[\\)]";
pattern = Pattern.compile(regexSimpleTan);
matcher = pattern.matcher(part2);
if (matcher.find()) {
// System.out.println("Строка является простым тангенсом");
if (part2.indexOf("-") > 0) addMinusOperation++;
Double r = Math.tan(Math.toRadians(Double.valueOf(part2.replace("tan(", "").replace(")", ""))));
strResult = String.format("%.2f", r).replace(",", ".");
part21 = "";
part22 = strResult;
part23 = "";
someCalculateComplete = true;
}
}
}
s("Ликвидация скобок, в том числе минусовых (без вычислений)");
{
if (!someCalculateComplete) {
pattern = Pattern.compile("[\\(]" + "[\\-]?" + simpleNumber + "[\\)]");
matcher = pattern.matcher(expressionWithoutBlanks);
if (matcher.find()) {
strResult = expressionWithoutBlanks.substring(matcher.start() + 1, matcher.end() - 1);
int start = matcher.start();
int end = matcher.end();
part1 = expressionWithoutBlanks.substring(0, start);
part2 = expressionWithoutBlanks.substring(start, end);
part3 = expressionWithoutBlanks.substring(end);
s("Часть 1: " + part1);
s("Часть 2: " + part2);
s("Часть 3: " + part3);
s("Были найдены ненужные скобки, они будут уничтожены");
recurse(expressionWithoutBlanks.substring(0, matcher.start()) + strResult + expressionWithoutBlanks.substring(matcher.end()), countOperation);
return;
}
}
if (!someCalculateComplete) {
pattern = Pattern.compile("[\\(]" + "[\\+]?" + simpleNumber + "[\\)]");
matcher = pattern.matcher(expressionWithoutBlanks);
if (matcher.find()) {
strResult = expressionWithoutBlanks.substring(matcher.start() + 1, matcher.end() - 1);
int start = matcher.start();
int end = matcher.end();
part1 = expressionWithoutBlanks.substring(0, start);
part2 = expressionWithoutBlanks.substring(start, end);
part3 = expressionWithoutBlanks.substring(end);
s("Часть 1: " + part1);
s("Часть 2: " + part2);
s("Часть 3: " + part3);
s("Были найдены ненужные скобки, они будут уничтожены");
recurse(expressionWithoutBlanks.substring(0, matcher.start()) + strResult + expressionWithoutBlanks.substring(matcher.end()), countOperation);
return;
}
}
}
s("Основной алгоритм по средней части: умножение, деление, сложение, возведение в степень ");
{
// проверка возведения в степень
if (!someCalculateComplete) {
s("Проверка возведения в степень [" + part2 + "]");
{
pattern = Pattern.compile(simpleNumber + "[\\^]" + "[\\-]?" + simpleNumber);
matcher = pattern.matcher(part2);
if (matcher.find()) {
s("Нашли простое возведение в степень");
String substringtoCalculate = part2.substring(matcher.start(), matcher.end());
String[] twoValues = substringtoCalculate.split("[\\^]");
Double d = Math.pow(Double.valueOf(twoValues[0]), Double.valueOf(twoValues[1]));
if (Double.valueOf(twoValues[0]) < 0) {
s("Первый аргумент был отриательным");
addMinusOperation++;
s("addMinusOperation " + addMinusOperation);
}
if (Double.valueOf(twoValues[1]) < 0) {
s("Второй аргумент был отриательным");
addMinusOperation++;
s("addMinusOperation " + addMinusOperation);
}
strResult = String.format("%.2f", d).replace(",", ".");
part21 = part2.substring(0, matcher.start());
part22 = strResult;
part23 = part2.substring(matcher.end());
someCalculateComplete = true;
}
}
}
// Проверка умножения
if (!someCalculateComplete) {
s("Проверка умножения");
{
pattern = Pattern.compile("[\\-]?" + simpleNumber + "[\\*]" + "[\\-]?" + simpleNumber);
matcher = pattern.matcher(part2);
if (matcher.find()) {
s("Нашли простое умножение");
String substringtoCalculate = part2.substring(matcher.start(), matcher.end());
String[] twoValues = substringtoCalculate.split("[\\*]");
Double d = Double.valueOf(twoValues[0]) * Double.valueOf(twoValues[1]);
if (Double.valueOf(twoValues[0]) < 0) {
s("Первый аргумент был отриательным");
addMinusOperation++;
s("addMinusOperation " + addMinusOperation);
}
if (Double.valueOf(twoValues[1]) < 0) {
s("Второй аргумент был отриательным");
addMinusOperation++;
s("addMinusOperation " + addMinusOperation);
}
strResult = String.format("%.2f", d).replace(",", ".");
part21 = part2.substring(0, matcher.start());
part22 = strResult;
part23 = part2.substring(matcher.end());
someCalculateComplete = true;
}
}
}
// проверка деления
if (!someCalculateComplete) {
s("Проверка деления");
{
pattern = Pattern.compile(simpleNumber + "[//]" + simpleNumber);
matcher = pattern.matcher(part2);
if (matcher.find()) {
s("Нашли простое деление");
String substringtoCalculate = part2.substring(matcher.start(), matcher.end());
String[] twoValues = substringtoCalculate.split("[//]");
Double d = Double.valueOf(twoValues[0]) / Double.valueOf(twoValues[1]);
strResult = String.format("%.2f", d).replace(",", ".");
part21 = part2.substring(0, matcher.start());
part22 = strResult;
part23 = part2.substring(matcher.end());
someCalculateComplete = true;
}
}
}
// проверка сложения
if (!someCalculateComplete) {
s("Проверка сложения [" + part2 + "]");
{
pattern = Pattern.compile("[\\-]?" + simpleNumber + "[+]" + "[\\-]?" + simpleNumber);
matcher = pattern.matcher(part2);
if (matcher.find()) {
s("Нашли простое сложение");
String substringtoCalculate = part2.substring(matcher.start(), matcher.end());
String[] twoValues = substringtoCalculate.split("[+]");
Double d = Double.valueOf(twoValues[0]) + Double.valueOf(twoValues[1]);
if (Double.valueOf(twoValues[0]) < 0) {
addMinusOperation = 1;
}
strResult = String.format("%.2f", d).replace(",", ".");
part21 = part2.substring(0, matcher.start());
part22 = strResult;
part23 = part2.substring(matcher.end());
someCalculateComplete = true;
}
}
}
// проверка вычитания
if (!someCalculateComplete) {
s("Проверка вычитания [" + part2 + "]");
{
pattern = Pattern.compile("[\\-]?" + simpleNumber + "[-]" + simpleNumber);
matcher = pattern.matcher(part2);
if (matcher.find()) {
s("Нашли простое вычитание");
String substringtoCalculate = part2.substring(matcher.start(), matcher.end());
String[] twoValues = substringtoCalculate.split("[-]");
Double d = Double.valueOf(twoValues[0]) - Double.valueOf(twoValues[1]);
if (Double.valueOf(twoValues[0]) < 0) {
addMinusOperation = 1;
}
strResult = String.format("%.2f", d).replace(",", ".");
part21 = part2.substring(0, matcher.start());
part22 = strResult;
part23 = part2.substring(matcher.end());
someCalculateComplete = true;
}
}
}
}
s("Часть 2.1: " + part21);
s("Часть 2.2: " + part22);
s("Часть 2.3: " + part23);
s("Реккурсивный дальнейший вызов");
recurse(part1 + part21 + part22 + part23 + part3, countOperation + 1 + addMinusOperation);
return;
// System.out.println(Math.round(Double.valueOf(String.format("%.2f", r).replace(",", "."))) + " " + (countOperation + 1));
// заблоченный кусок кода
// if (false) {
// {
//// System.out.println("После зачистки пробелов: " + expressionWithoutBlanks);
// // если простое число, то 0 операций
// if (expression.matches("[\\(]?" + simpleNumber + "[\\)]?")) {
// s("Простое число");
//// String strToCalc = expressionWithoutBlanks.substring(matcher.start(), matcher.end());
//// System.out.println(Double.valueOf(expression.replace("(","").replace("(","")) + " " + (countOperation + 1));
// NumberFormat format = new DecimalFormat("#.##");
// String witoutSkobka = expression.replace("(", "").replace("(", "");
// System.out.println(String.format("%s %d", String.format("%.2f", Double.valueOf(witoutSkobka)), countOperation));
// return;
// }
//
//
//
//
//
//// System.out.println("Ликвидация кобок");
// pattern = Pattern.compile("[\\(]" + simpleNumber + "[\\)]");
// matcher = pattern.matcher(expressionWithoutBlanks);
// if (matcher.find()) {
// String strToCalc = expressionWithoutBlanks.substring(matcher.start() + 1, matcher.end() - 2);
// recurse(expressionWithoutBlanks.substring(0, matcher.start()) + strToCalc + expressionWithoutBlanks.substring(matcher.end()), countOperation + 1);
// return;
// }
//
//// System.out.println("Ищем отрицательное умножение");
// pattern = Pattern.compile(simpleNumber + "[\\*][\\(][\\-]" + simpleNumber + "[\\)]");
// matcher = pattern.matcher(expressionWithoutBlanks);
// if (matcher.find()) {
// String strToCalc = expressionWithoutBlanks.substring(matcher.start(), matcher.end());
// String[] twoValues = strToCalc.split("[\\*]");
//// System.out.println("Первое число: " + twoValues[0]);
//// System.out.println("Второе число: " + twoValues[1].replace("(","").replace(")", ""));
// Double d = Double.valueOf(twoValues[0]) * Double.valueOf(twoValues[1].replace("(", "").replace(")", ""));
// strResult = String.format("%.2f", d).replace(",", ".");
//// System.out.println("Прокидываем");
// recurse(expressionWithoutBlanks.substring(0, matcher.start()) + strResult + expressionWithoutBlanks.substring(matcher.end()), countOperation + 1);
// return;
// }
//
//// System.out.println("Простых умножений не нашли, ищем простые сложения");
// pattern = Pattern.compile("[\\-]?" + simpleNumber + "[\\+]" + simpleNumber);
// matcher = pattern.matcher(expressionWithoutBlanks);
// if (matcher.find()) {
// s("Нашли простое сложение");
// String strToCalc = expressionWithoutBlanks.substring(matcher.start(), matcher.end());
// String[] twoValues = strToCalc.split("[\\+]");
//// System.out.println("Первое число: " + twoValues[0]);
//// System.out.println("Второе число: " + twoValues[1]);
// Double d = Double.valueOf(twoValues[0]) + Double.valueOf(twoValues[1]);
// strResult = String.format("%.2f", d).replace(",", ".");
//// System.out.println("Прокидываем");
// recurse(expressionWithoutBlanks.substring(0, matcher.start()) + strResult + expressionWithoutBlanks.substring(matcher.end()), countOperation + 1);
// return;
// }
//
//
//// // если это простое умножение
//// String regexSimpleMultiply = simpleNumber + "[\\*]" + simpleNumber;
//// if(Pattern.matches(regexSimpleMultiply, expressionWithoutBlanks)) {
//// System.out.println("Строка является простым умножением");
//// String[] twoValues = expressionWithoutBlanks.split("[\\*]");
//// System.out.println("Первое число: " + twoValues[0]);
//// System.out.println("Второе число: " + twoValues[1]);
//// Double d = Double.valueOf(twoValues[0]) * Double.valueOf(twoValues[1]);
//// System.out.println(String.format("%.2f",d).replace(",", ".") + " " + (countOperation + 1));
//// }
//
// // это простое отрицание
//// System.out.println("Ищем простое вычитание");
// String regexSimpleMinus = "[\\-]?" + simpleNumber + "[\\-]" + simpleNumber;
// pattern = Pattern.compile(regexSimpleMinus);
// matcher = pattern.matcher(expressionWithoutBlanks);
// if (matcher.find()) {
// String strToCalc = expressionWithoutBlanks.substring(matcher.start(), matcher.end());
//// System.out.println("Работаем со строкой: " + strToCalc);
// String[] twoValues = strToCalc.split("[\\-]");
//// System.out.println("Первое число: " + twoValues[0]);
//// System.out.println("Второе число: " + twoValues[1]);
// Double d = Double.valueOf(twoValues[0]) + Double.valueOf(twoValues[1]);
// strResult = String.format("%.2f", d).replace(",", ".");
//// System.out.println("Прокидываем");
// recurse(expressionWithoutBlanks.substring(0, matcher.start()) + strResult + expressionWithoutBlanks.substring(matcher.end()), countOperation + 1);
// return;
// }
//
// // это простое возведение в степень
//// System.out.println("Ищем возведение в степень");
// String regexSimpleExponentation = simpleNumber + "[\\^]" + simpleNumber;
// pattern = Pattern.compile(regexSimpleExponentation);
// matcher = pattern.matcher(expressionWithoutBlanks);
//// String regexSimpleExponentation = "5" ;
// if (matcher.find()) {
// String strToCalc = expressionWithoutBlanks.substring(matcher.start(), matcher.end());
//// System.out.println("Работаем со строкой: " + strToCalc);
// String[] twoValues = strToCalc.split("[\\^]");
//// System.out.println("Первое число: " + twoValues[0]);
//// System.out.println("Второе число: " + twoValues[1]);
// Double r = Math.pow(Double.valueOf(twoValues[0]), Double.valueOf(twoValues[1]));
//// System.out.println(String.format("%.2f",r).replace(",", ".") + " " + (countOperation + 1));
// recurse(expressionWithoutBlanks.substring(0, matcher.start()) + r.toString() + expressionWithoutBlanks.substring(matcher.end()), countOperation + 1);
// return;
// }
//
//
//// System.out.println(countOperation + "Выражение оказалось сложным. Надо упрощать...");
//// System.out.println(countOperation + "Необходимо из определенного подвыражения получить новую строку и кинуть вычисление в новый вызов...");
////
//// System.out.println(countOperation + "Пробуем найти подслово с умножением...");
////
// s("Дошли до конца. Просто печатаем результат");
//// System.out.println(Math.round(Double.valueOf(String.format("%.2f",r).replace(",", "."))) + " " + (countOperation + 1));
//
// }
// }
}
}