JavaRush /Java Blog /Random-KO /레벨 10 JavaRush(CodeWars의 3Kyu 작업)만을 기반으로 하는 Java 계산기

레벨 10 JavaRush(CodeWars의 3Kyu 작업)만을 기반으로 하는 Java 계산기

Random-KO 그룹에 게시되었습니다
CodeWars에서의 나의 모험에 관한 또 다른 기사입니다. 이를 위해 기본 계산기의 기능을 구현합니다. 연산자 문자열(), +, -, *, /가 제공되는 간단한 계산기를 만듭니다 . 레벨 10 JavaRush(CodeWars의 3Kyu 작업)만을 기반으로 하는 Java 계산기 - 1내 벨트에는 10개 이상의 JavaRush 레벨만 있으므로 코드가 상당히 번거롭지만 완벽하게 작동합니다. 아시다시피 이 작업은 CodeWars 웹사이트에서 가져온 것입니다 . 그녀의 순위는 3급 이다 . 비공개 메시지로 링크를 알려드릴 수 있습니다. 다음은 나에게 도움이 된 방법 및 프로세스의 일부 목록입니다.
  1. 재귀. 이 경우 괄호를 없애기 위해서는 메소드가 자신을 호출하는(처음 사용하는 경우 :)) 과정이 필요합니다.
  2. 메소드 String'a trim(), split(), substring(), replace().
  3. 기본 수집 방법 List.
  4. 유형 변환도 가능 Double합니다 String.
원칙적으로 이것으로 충분합니다. 코드 자체로 넘어가기 전에 제가 어떤 함정을 겪었는지 말씀드리겠습니다. 대부분 이것은 계산이 수행되는 순서입니다. 처음에는 표준 구성표를 만들었지 * > / > + > -만 예를 들어 이 옵션을 사용하면 12/6 * 32/2프로그램이 먼저 곱셈( 6*32)을 수행하고 모든 것이 내리막길로 진행된다는 것을 깨달았습니다. 그래서 순서는 다음과 같이 되었습니다: * > / > + > -. 몇 시간 더 지나서 나는 가장 큰 조약돌을 발견했습니다 -. 다양한 위치와 다양한 조합으로 그는 모든 것을 변화시켰습니다 . (물론 이것은 내 잘못입니다. 예를 들어 , -34목록의 한 셀이 아니라 두 셀에 있습니다. 하나는 - 다른 하나는 34). 이 때문에 우리는 를 사용하여 계산에 2개의 추가 논리를 작성해야 했습니다 -. 일반적으로 코드에서 이를 볼 수 있습니다. 코드에 불필요한 코멘트를 한 점 사과드리며, 제 생각의 흐름을 최대한 공개하고 거기에서 무슨 일이 일어나고 있는지 설명하고 싶었습니다.
import java.util.*;

public class Calculator {
    public static void main(String[] args) {
        String num = "2 / ( ( 2 + 0 ) * 1 ) - 6";
        System.out.println(evaluate(num));
    }

    public static Double evaluate(String expression) {

//  Этап 1
//  На данном этапе преобразуем нашу строку в список строк, через совмещение цикла for-each и метода split(),
//  также используем метод trim(), чтобы избавиться от пробелов по краям.
//  Обратите внимание, что каждым вторым элиментом я добавляю " ". Для того, чтобы потом мне было легче работать со строкой

        List<string> strList = new ArrayList<>();
        for (String listElement : expression.trim().split(" ")) {
            strList.add(listElement);
            strList.add(" ");
        }
        strList.remove(strList.size() - 1);
//        for (String x : strList) System.out.print(x + "");
//        System.out.println();
//        После того, How дочитаете code до конца, расскоментируйте две верхние строчки
//        и посмотрите How работает рекрусия

//  Этап 2
//  Производим поиск символа "(" в списке если находим, то преобразуем все символы от '(' до последнего ')' в строку.
//  Надо быть внимательными и проверить на случай двух контрукций: 1) (())  2) ()().
//  P.S. После получения строки мы используем РЕКУРСИЮ (метод вызывает сам себя). Таким образом будем находить произведение скобок.

        if (strList.indexOf("(") != -1) {
//          Если "(" обнаружен, ищем подходящую конструкцию используя цикл.

            for (int i = strList.indexOf("(") + 1; i < strList.size() - 1; i++) {
//
//              Конструкция 1: первым элиментом, который мы отыскали были вторые "("
                String recursion = "";
                if (strList.get(i).equals("(")) {
                    for (int j = i; j < strList.lastIndexOf(")"); j++) {
                        recursion += strList.get(j);
                    }
                    // сверху считывали последовательность находящуюся в скобках (()) До lastIndex element
                    String test = expression.substring(expression.indexOf("("), expression.lastIndexOf(")") + 1);
                    // test - последовательность How и сверху, но с добавлением скобок по краям

                    // т.к. наш метод evaluate() возвращает Double, мы должны преобразовать результат рекрусии в String;
                    String testRecursion = String.valueOf(evaluate(recursion));
                    expression = expression.replace(test, testRecursion);
                    // преобразовали нашу строку с использование рекруси. Избавorсь от первых скобок
                    strList.removeAll(strList);
                    for (String newElement : expression.trim().split(" ")) {
                        strList.add(newElement);
                        strList.add(" ");
                    }
                    // Тут очищаем наш список и сново его заполняем (но уже раскрыв первые скобки)
                }

//                Конструкция 2: первым элиментом, который мы отыскали был  ")"
                String recursion2 = "";
                if (strList.get(i).equals(")")) {

                    for (int j = strList.indexOf("(") + 1; j < strList.indexOf(")"); j++) {
                        recursion2 += strList.get(j);
                    }
                    String test2 = expression.substring(expression.indexOf("("), expression.lastIndexOf(")") + 1);
                    String testRecursion2 = String.valueOf(evaluate(recursion2));
                    expression = expression.replace(test2, testRecursion2);
                    for (String newElement : expression.trim().split(" ")) {
                        strList.add(newElement);
                        strList.add(" ");
                    }
                    // Тут повторor тот же алгоритм, что и в первой конструкции
                }
            }
        }

//  Этап 3
//  Заключительный этап на котором мы будем реализовывать сами вычесления (*/-+)
//  Всю реализацию помещаем в цикл while ( который прекратиться, если все действия будут выполнены (соответственно в списке останется 1 элемент)).
//  Внимательно посмотрите на порядок операций: 1)/ 2)* 3)- 4)+

//        System.out.println(expression + "-------expression-");
//        System.out.println();
        // создаем очередной список для реализации вычеслений, на этот раз без добавления " ".
        List<string> stringList2 = new ArrayList<>();
        for (String element : expression.trim().split(" ")) {
            stringList2.add(element);
        }


        while (stringList2.size() != 0) {
//          работаем со списком: глубоком этапе рекрусии обрабатываем:  (2+0)
//          на среднем: 1 * 1  "or вот этой части уравнения "( ( 2 + 0 ) * 1 ) "
//          Посмтортите сами
//            for (String x : stringList2) System.out.print(x );
//            System.out.println();

            // наш Double :) Также стоит обратить внимание, что для получения класса обертки мы используем не
            // Double.parseDouble() а Double.valueOf()
             Double result = 0d;

//  Сами алгоритмы вычеслений, впринципе понятны, поэтому не буду их комментировать.
//  Однако обратите внимание на очередность, особенно при вычетании (там instead of 1 условия, 3)
//  Если что в комментариях под постом немного объясню, если кто-нибудь дочитает до сюда и у него будет желание)
            if (stringList2.indexOf("/") != -1) {
                int index = stringList2.indexOf("/");
                result = Double.valueOf(stringList2.get(index - 1)) / Double.valueOf(stringList2.get(index + 1));
                stringList2.add(index - 1, String.valueOf(result));
                stringList2.remove(index + 2);
                stringList2.remove(index + 1);
                stringList2.remove(index);
            }
            else if (stringList2.indexOf("*") != -1) {
                int index = stringList2.indexOf("*");
                result = Double.valueOf(stringList2.get(index - 1)) * Double.valueOf(stringList2.get(index + 1));
                stringList2.add(index - 1, String.valueOf(result));
                stringList2.remove(index + 2);
                stringList2.remove(index + 1);
                stringList2.remove(index);
            }
            else if (stringList2.indexOf("-") != -1) {
                int index = stringList2.indexOf("-");
                int lastIndex = stringList2.lastIndexOf("-");
                if (index == 0) {
                    result = 0.0 - Double.valueOf(stringList2.get(index + 1));
                    stringList2.add(0, String.valueOf(result));
                    stringList2.remove(2);
                    stringList2.remove(1);
                }
                else if ((lastIndex-2>0) && (stringList2.get(lastIndex-2).equals("-"))){
                    result = Double.valueOf(stringList2.get(lastIndex + 1)) + Double.valueOf(stringList2.get(lastIndex - 1));
                    stringList2.add(lastIndex - 1, String.valueOf(result));
                    stringList2.remove(lastIndex + 2);
                    stringList2.remove(lastIndex + 1);
                    stringList2.remove(lastIndex);
                }
                else {
                    result = Double.valueOf(stringList2.get(index - 1)) - Double.valueOf(stringList2.get(index + 1));
                    stringList2.add(index - 1, String.valueOf(result));
                    stringList2.remove(index + 2);
                    stringList2.remove(index + 1);
                    stringList2.remove(index);
                }
            }
            else if (stringList2.indexOf("+") != -1) {
                int index = stringList2.indexOf("+");
                result = Double.valueOf(stringList2.get(index - 1)) + Double.valueOf(stringList2.get(index + 1));
                stringList2.add(index - 1, String.valueOf(result));
                stringList2.remove(index + 2);
                stringList2.remove(index + 1);
                stringList2.remove(index);
            }

            // Вот тут все немного коряво. (На всякий случий проверял отсутствие (*/+-))
            if ((stringList2.indexOf("*") == -1) && (stringList2.indexOf("/") == -1) && (stringList2.indexOf("+") == -1) && (stringList2.indexOf("-") == -1)) {
                return result;
            }
        }
        return Double.valueOf(stringList2.get(0));
    }
}
</string></string>
읽고 댓글을 남겨주신 모든 분들께 감사드립니다.) 댓글이 있거나 있을 가능성이 높으면 기꺼이 듣겠습니다.)
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION