Помогите понять что не так.
package com.javarush.task.task34.task3404;
import java.io.StringReader;
import java.math.RoundingMode;
import java.text.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*
Рекурсия для мат. выражения
*/
public class Solution {
public static void main(String[] args) throws ParseException {
Solution solution = new Solution();
solution.recurse("2+8*(9/4-1.5)^(1+1)", 0); // Expected output: 0.5 6 1+(1+2*2)*(1+1)+1 "sin(45) - cos(45)"
// ВЫРАЖЕНИЯ ДЛЯ ПРОВЕРКИ
// sin(cos(60)*60)*cos(45) * tan(56.25) / ((sin(30+45)+sin(30-45))/(cos(60)*2.0^2.0)) // 1.5 17
// "sin(cos(60)*60)*cos(45) * tan(56.25) / ((sin(30+45)+sin(30-45))/(cos(60)*2.0^2.0))"
//"sin(cos(60)*60)*cos(45) * tan(56.25) / ((sin(30+45)+sin(30-45))/(cos(60)*2.0^2.0))"
/* solution.recurse("tan(45)", 0); System.out.println("1 1 - expected output");
solution.recurse("tan(-45)", 0); System.out.println("-1 2 - expected output");
solution.recurse("1+(1+(1+1)*(1+1))*(1+1)+1", 0); System.out.println("12 8 - expected output");
solution.recurse("tan(44+sin(89-cos(180)^2))", 0); System.out.println("1 6 - expected output");
solution.recurse("-2+(-2+(-2)-2*(2+2))", 0); System.out.println("-14 8 - expected output");
solution.recurse("sin(80+(2+(1+1))*(1+1)+2)", 0); System.out.println("1 7 - expected output");
solution.recurse("10-2^(2-1+1)", 0); System.out.println("6 4 - expected output");
solution.recurse("2^10+2^(5+5)", 0); System.out.println("2048 4 - expected output");
solution.recurse("0.000025+0.000012", 0); System.out.println("0 1 - expected output");
solution.recurse("-2-(-2-1-(-2)-(-2)-(-2-2-(-2)-2)-2-2)", 0); System.out.println("-3 16 - expected output");
solution.recurse("cos(3 + 19*3)", 0); System.out.println("0.5 3 - expected output");
solution.recurse("(-1 + (-2))", 0); System.out.println("-3 3 - expected output");
solution.recurse("-sin(2*(-5+1.5*4)+28)", 0); System.out.println("-0.5 7 - expected output");
solution.recurse("sin(100)-sin(100)", 0); System.out.println("0 3 - expected output");
solution.recurse("-(-22+22*2)", 0); System.out.println("-22 4 - expected output");
solution.recurse("(-2)*(-2)", 0); System.out.println("4 3 - expected output");
solution.recurse("(-2)/(-2)", 0); System.out.println("1 3 - expected output");
solution.recurse("sin(-30)", 0); System.out.println("-0.5 2 - expected output");
solution.recurse("cos(-30)", 0); System.out.println("0.87 2 - expected output");
solution.recurse("tan(-30)", 0); System.out.println("-0.58 2 - expected output");
solution.recurse("2+8*(9/4-1.5)^(1+1)", 0); System.out.println("6.5 6 - expected output");
solution.recurse("0+0.304", 0); System.out.println("0.3 1 - expected output");
solution.recurse("sin(45) - cos(45)", 0); System.out.println("0 3 - expected output");
solution.recurse("0/(-3)", 0); System.out.println("-0 2 - expected output");
solution.recurse("1+4/2/2+2^2+2*2-2^(2-1+1)", 0); System.out.println("6 11 - expected output");
solution.recurse("0.005", 0); System.out.println("0.01 0 - expected output");
solution.recurse("0.0049", 0); System.out.println("0 0 - expected output");
solution.recurse("-2^(-2)", 0); System.out.println("0.25 3 - expected output");
solution.recurse("-1*-1.00^2",0); System.out.println("-1 4 - expected output");
solution.recurse("-1*-1.0^2",0); System.out.println("-1 4 - expected output");
solution.recurse("-1*(-1.00)^2",0); System.out.println("-1 4 - expected output");
solution.recurse("-(-2^(-2))+2+(-(-2^(-2)))", 0); System.out.println("1.5 10 - expected output");
solution.recurse("1.01+(2.02-1+1/0.5*1.02)/0.1+0.25+41.1", 0); System.out.println("72.96 8 - expected output");
solution.recurse("2*(589+((2454*0.1548/0.01*(-2+9^2))+((25*123.12+45877*25)+25))-547)", 0); System.out.println("8302231.36 14 - expected output");
solution.recurse("0.305", 0); System.out.println("0.3 0 - expected output");
solution.recurse("0.3051", 0); System.out.println("0.31 - expected output");
solution.recurse("(0.3051)", 0); System.out.println("0.31 - expected output");
solution.recurse("0", 0); System.out.println("0 0 - expected output");
solution.recurse("(0)", 0); System.out.println("0 0 - expected output");
solution.recurse("-(0)", 0); System.out.println("-0 1 - expected output");*/
}
public void recurse(final String expression, int countOperation) throws ParseException {
//implement
if(expression.contains(" ")) {
recurse(expression.replaceAll(" ", ""), countOperation);
return;
}
// System.out.println(expression + " count = " + countOperation);
countOperation++; //считаем количество операций
if(expression.contains("--")){
recurse(expression.replaceFirst("--","+"),countOperation);
}
else if(expression.contains("++")){
recurse(expression.replaceFirst("\\+\\+","+"),countOperation);
}
else if(expression.contains("+-")){
recurse(expression.replaceFirst("\\+-","-"),countOperation);
}
else if(expression.contains("-+")){
recurse(expression.replaceFirst("-\\+","-"),countOperation);
}
//если приходит число с множеством вложенных скобок или без них
else if(expression.matches("\\(*[+-]?\\d+(\\.?\\,?\\d+)?\\)*")){
DecimalFormatSymbols otherSymbols = new DecimalFormatSymbols(Locale.US);
String pat = "#.##";
DecimalFormat decimalFormat = new DecimalFormat(pat, otherSymbols);
if(expression.contains("-")) countOperation++;
if(expression.contains("(")) {
System.out.println(decimalFormat.format(decimalFormat.parse(expression.replaceAll("[\\(\\)]", ""))) + " " + --countOperation);
return;
}
System.out.println(String.format("%s %d",decimalFormat.format(decimalFormat.parse(expression)), --countOperation));
return;
}
//если выражение с во вложенных скобках
else if(expression.matches(".*\\({2}([\\.\\+^[*/]])+\\){2}.*")){ //".*\\({2}.+\\){2}.*"
Pattern pattern = Pattern.compile("\\({2}.+\\){2}");
Matcher matcher = pattern.matcher(expression);
matcher.find();
String s = matcher.group();
recurse(expression.replace(s, s.substring(1,s.length()-1)),--countOperation); //если пара скобок, оставляем только одни
return;
}
// если sin cos tan внутри выражения
else if(expression.matches(".*(sin|cos|tan)\\([+-]?\\d+(\\.?\\,?\\d+)?\\).*")){
Pattern pattern = Pattern.compile("(sin|cos|tan)\\([+-]?\\d+(\\.?\\,?\\d+)?\\)");
Matcher matcher = pattern.matcher(expression);
matcher.find();
String s = matcher.group();
String res = calculate(s);
if(res.charAt(0)=='-') countOperation--;
if(s.contains("-")) countOperation++;
recurse(expression.replaceFirst("(sin|cos|tan)\\([+-]?\\d+(\\.?\\,?\\d+)?\\)", res),countOperation);
}
// возведение в степень
else if(expression.matches(".*\\d+(\\.?\\,?\\d+)?\\^-?\\d+(\\.?\\,?\\d+)?.*") || expression.matches(".*\\(?-?\\d+(\\.?\\,?\\d+)?\\)?\\^\\(-?\\d+(\\.?\\,?\\d+)?\\).*")){
Pattern pattern = null;
if(expression.matches("((^)|(.*\\()|(.*[*/^]))-\\d+(\\.?\\,?\\d+)?\\)?\\^\\(?-?\\d+(\\.?\\,?\\d+)?\\)?.*")){ // если начало строки или скобка впереди или */^ (^)|
pattern = Pattern.compile("-\\d+(\\.?\\,?\\d+)?\\^\\(?-?\\d+(\\.?\\,?\\d+)?\\)?"); // тогда берем -
}else if(expression.matches(".*-\\d+(\\.?\\,?\\d+)?\\^\\(?-?\\d+(\\.?\\,?\\d+)?\\)?.*")){ //
pattern = Pattern.compile("\\d+(\\.?\\,?\\d+)?\\^\\(?-?\\d+(\\.?\\,?\\d+)?\\)?"); // без минуса
}
else if (expression.matches(".*\\d+(\\.?\\,?\\d+)?\\^\\(-?\\d+(\\.?\\,?\\d+)?\\).*")){ //если степень в скобках
pattern = Pattern.compile("\\(?-?\\d+(\\.?\\,?\\d+)?\\)?\\^\\(-?\\d+(\\.?\\,?\\d+)?\\)");
}else {
pattern = Pattern.compile("\\(?-?\\d+(\\.?\\,?\\d+)?\\)?\\^-?\\d+(\\.?\\,?\\d+)?"); //если степень без скобок
}
Matcher matcher = pattern.matcher(expression);
matcher.find();
String s = matcher.group();
Pattern pattern2 = Pattern.compile("-\\d{1}");
matcher = pattern2.matcher(s);
while (matcher.find()){ // считаем минусы
countOperation++;
}
countOperation += matcher.groupCount();
if(calculate(s).charAt(0)=='-'){
countOperation--;
}
recurse(expression.replaceFirst(pattern.toString(), calculate(s)),countOperation);
}
// выражение в скобках
else if(expression.contains("(")) {
Pattern pattern = Pattern.compile("\\([^\\(]+?\\)");
Matcher matcher = pattern.matcher(expression);
matcher.find();
String s = matcher.group();
if(s.matches("\\([+-]?\\d+(\\.?\\,?\\d+)?\\)")){
recurse(expression.replaceFirst("\\([+-]?\\d+(\\.?\\,?\\d+)?\\)", calculate(s)), --countOperation);
}
else {
if(s.charAt(1) == '-' && calculate(s).charAt(1)!='-'){
countOperation++;
}
matcher.usePattern(Pattern.compile(".*(sin)|(cos)|(tan)"+s));
// System.out.println(matcher.lookingAt());
//System.out.println(matcher.lookingAt());
if(s.contains("-") && matcher.lookingAt() && calculate(s).matches("\\(-\\d+(\\.?\\,?\\d+)?\\)")){
countOperation--;
}
recurse(expression.replaceFirst("\\([^\\(]+?\\)", calculate(s)), countOperation); //"\\([^\\(]+?\\)"
}
}
// умножение и деление
else if(expression.matches(".*\\d+(\\.?\\,?\\d+)?[*/]-?\\d+(\\.?\\,?\\d+)?.*")){
Pattern pattern = Pattern.compile("-?\\d+(\\.?\\,?\\d+)?[*/]-?\\d+(\\.?\\,?\\d+)?");
Matcher matcher = pattern.matcher(expression);
matcher.find();
String s = matcher.group();
if(s.split("[*/]")[0].contains("-")&&s.split("[*/]")[1].contains("-")) {
countOperation+=2;
}
String res = calculate(s);
recurse(expression.replace(s, res),countOperation);
}
// сложение и вычитание
else if(expression.matches("[+-]?\\d+(\\.?\\,?\\d+)?[+-]-?\\d+(\\.?\\,?\\d+)?.*")){
Pattern pattern = Pattern.compile("[+-]?\\d+(\\.?\\,?\\d+)?+([+-]-?\\d+(\\.?\\,?\\d+)?)");
Matcher matcher = pattern.matcher(expression);
matcher.find();
String s = matcher.group();
if(s.charAt(0) == '-' && calculate(s).charAt(0)!='-') {
countOperation++;
}
recurse(expression.replaceFirst(pattern.toString(), calculate(s)),countOperation);
}
}
public String calculate (String expression) throws ParseException { //метод для выполнения одной операции
if(expression.matches("\\([+-]?\\d+(\\.?\\,?\\d+)?\\)") && !expression.matches("(sin|cos|tan)")) {
return expression.substring(1,expression.length()-1);
}
DecimalFormatSymbols otherSymbols = new DecimalFormatSymbols(Locale.US);
String pat = "#0.#######";
DecimalFormat decimalFormat = new DecimalFormat(pat, otherSymbols);
ParsePosition parsePosition = new ParsePosition(0);
if(expression.matches("(sin|cos|tan)\\(?[+-]?\\d+(\\.?\\,?\\d+)?\\)?")) {
Pattern pattern = Pattern.compile("(sin|cos|tan)\\(?[+-]?\\d+(\\.?\\,?\\d+)?\\)?");
Matcher matcher = pattern.matcher(expression);
matcher.find();
String s = matcher.group();
Double result = null;
switch (expression.charAt(0)){ //смотрим по первому символу sin cos или tan
case 's':
result = Math.sin(Math.toRadians(getDigitFromExp(expression.substring(3),parsePosition)));
break;
case 'c':
result = Math.cos(Math.toRadians((getDigitFromExp(expression.substring(3),parsePosition))));
break;
case 't':
result = Math.tan(Math.toRadians((getDigitFromExp(expression.substring(3),parsePosition))));
break;
}
return expression.replace(s,decimalFormat.format(result));
}
if(expression.matches("(.*)[*/^](.*)")){
Pattern pattern = null;
if(expression.matches("\\(.*\\)"))
{
pattern = Pattern.compile("-?\\d+(\\.?\\d+)?[*/^]-?\\d+(\\.?\\d+)?");
}
else
pattern = Pattern.compile("-?\\d+(\\.?\\d+)?[*/^]\\(?-?\\d+(\\.?\\d+)?\\)?");
Matcher matcher = pattern.matcher(expression);
matcher.find();
String s = matcher.group();
Double number_1, number_2;
if(s.contains("(") && !s.contains(")")) s.replaceAll("[\\(]","");
else if(s.contains(")") && !s.contains("(")) s.replaceAll("[\\)]","");
double result = 0.0;
number_1 = getDigitFromExp(s.replaceAll("[\\(\\)]",""),parsePosition);
number_2 = getDigitFromExp(s.replaceAll("[\\(\\)]",""),parsePosition);
if(s.contains("*")){
result = number_1 * number_2;
}
else if(s.contains("/")){
result = number_1 / number_2;
}
else if(s.contains("^")){
result = Math.pow(number_1, number_2);
}
return expression.replace(s, decimalFormat.format(result));
}
if(expression.matches("\\(?([+-]?-?\\d+(\\.?\\,?\\d+)?){2,}\\)?")){
Pattern pattern = Pattern.compile("(([+-]?-?\\d+(\\.?\\,?\\d+)?)){2}");
Matcher matcher = pattern.matcher(expression);
matcher.find();
String s = matcher.group();
Double number_1, number_2;
number_1 = getDigitFromExp(s,parsePosition);
number_2 = getDigitFromExp(s,parsePosition);
return expression.replace(s, decimalFormat.format(number_1 + number_2));
}
return null;
}
public Double getDigitFromExp(String expression, ParsePosition parsePosition){ //метод для парсинга дабл из стринг выражения
DecimalFormatSymbols otherSymbols = new DecimalFormatSymbols(Locale.US);
String pattern = "##.#######";
DecimalFormat decimalFormat = new DecimalFormat(pattern, otherSymbols);
Number number = decimalFormat.parse(expression, parsePosition);
while (number == null && parsePosition.getIndex() != expression.length()){ //если попдается непарсящийся знак (+ например)
parsePosition.setIndex(parsePosition.getIndex()+1); // прибавляем индекс пока не спарсится
number = decimalFormat.parse(expression, parsePosition);
}
if (number==null) return null; // если не спарсилось
return number.doubleValue();
}
public Solution() {
//don't delete
}
}