JavaRush /مدونة جافا /Random-AR /آلة حاسبة بلغة Java بقاعدة JavaRush من المستوى 10 فقط (تح...

آلة حاسبة بلغة Java بقاعدة JavaRush من المستوى 10 فقط (تحدي 3Kyu على CodeWars)

نشرت في المجموعة
مقال آخر عن مغامراتي في CodeWars. لهذا قمنا بتنفيذ وظيفة الآلة الحاسبة الأولية: قم بإنشاء آلة حاسبة بسيطة توفر سلسلة من عوامل التشغيل ()، +، -، *، / . آلة حاسبة في Java بقاعدة JavaRush من المستوى 10 فقط (مهمة 3Kyu على CodeWars) - 1لدي أكثر من 10 مستويات فقط من JavaRush تحت حزامي، لذا فإن الكود مرهق للغاية، لكنه يعمل بشكل مثالي. المهمة، كما لاحظت، تأتي من موقع CodeWars الإلكتروني . رتبتها هي 3kyu . يمكنني أن أعطيك الرابط في رسالة خاصة. فيما يلي قائمة جزئية بالأساليب والعمليات التي ساعدتني:
  1. العودية. تعد العملية التي تستدعي فيها الطريقة نفسها (أول مرة تستخدمها :)) ضرورية في هذه الحالة للتخلص من الأقواس.
  2. طرق , , . String_ _trim()split()substring()replace()
  3. طرق الجمع الأساسية List.
  4. وكذلك نوع التحويل Doubleمن Stringوإلى.
من حيث المبدأ، وهذا يكفي. قبل الانتقال إلى الكود نفسه، سأخبرك بالمزالق التي واجهتها. بالنسبة للجزء الأكبر، هذا هو الترتيب الذي يتم به تنفيذ العمليات الحسابية، في البداية قمت بعمل مخطط قياسي * > / > + > -، لكنني أدركت أنه، على سبيل المثال، مع هذا الخيار: 12/6 * 32/2سيقوم البرنامج أولاً بإجراء الضرب ( 6*32) وسيذهب كل شيء إلى أسفل، فأصبح الترتيب هكذا : * > / > + > -. وبعد ساعتين أخريين عثرت على أكبر حصاة - -. في مواقف مختلفة ومع مجموعات مختلفة، قام بتغيير كل شيء . (وهذا بالطبع خطأي، لأنه، على سبيل المثال: -34، لا يكمن في خلية واحدة من القائمة، بل في خليتين: في واحدة، - في الأخرى، 34). ولهذا السبب، كان علينا أن نكتب منطقين إضافيين في الحسابات -، بشكل عام، ستشاهد هذا في الكود. أعتذر عن التعليقات غير الضرورية في الكود، وأردت الكشف عن سلسلة أفكاري قدر الإمكان وشرح ما يحدث هناك.
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