JavaRush /وبلاگ جاوا /Random-FA /ماشین حساب در جاوا با پایه فقط lvl 10 JavaRush (وظیفه 3Ky...

ماشین حساب در جاوا با پایه فقط lvl 10 JavaRush (وظیفه 3Kyu در CodeWars)

در گروه منتشر شد
مقاله دیگری در مورد ماجراهای من در CodeWars. برای این کار ما عملکرد یک ماشین حساب ابتدایی را پیاده سازی می کنیم: یک ماشین حساب ساده ایجاد کنید که یک رشته از عملگرها ()، +، -، *، / . ماشین حساب در جاوا با پایه فقط lvl 10 JavaRush (وظیفه 3Kyu در CodeWars) - 1من فقط بیش از 10 سطح JavaRush در زیر کمربندم دارم، بنابراین کد بسیار دست و پا گیر است، اما کاملاً کار می کند. کار، همانطور که ممکن است متوجه شده باشید، از وب سایت CodeWars است . رتبه او 3kyu است . میتونم لینکش رو تو پیام خصوصی بدم در اینجا یک لیست جزئی از روش ها و فرآیندهایی است که به من کمک کرده است:
  1. بازگشت. فرآیندی که در آن یک متد خود را فراخوانی می کند (برای اولین بار با استفاده از آن :)) در این مورد برای خلاص شدن از شر پرانتز ضروری است.
  2. روشهای Stringa 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