บทความอื่นเกี่ยวกับการผจญภัยของฉันใน CodeWars สำหรับสิ่งนี้ เราได้นำฟังก์ชันการทำงานของเครื่องคิดเลขพื้นฐานมาใช้: สร้างเครื่องคิดเลขอย่างง่ายโดยกำหนดสตริงของตัวดำเนินการ (), +, -, *, /
ฉันมี JavaRush เพียง 10+ ระดับเท่านั้น ดังนั้นโค้ดจึงค่อนข้างยุ่งยาก แต่ก็ทำงานได้อย่างสมบูรณ์แบบ งานที่คุณอาจสังเกตเห็นนั้นมาจากเว็บไซต์CodeWars อันดับของเธอคือ3kyu ฉันสามารถให้ลิงค์ในข้อความส่วนตัวได้ นี่คือรายการวิธีการและกระบวนการบางส่วนที่ช่วยฉันได้:
- การเรียกซ้ำ กระบวนการที่เมธอดเรียกตัวเอง (ใช้งานครั้งแรก :)) เป็นสิ่งจำเป็นในกรณีนี้เพื่อกำจัดวงเล็บ
- วิธีการ
String
'atrim()
,split()
,substring()
,replace()
. - วิธีการรวบรวม
List
เบื้องต้น - รวมถึงการแปลงประเภท
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>
ขอบคุณทุกคนที่อ่านและแสดงความคิดเห็น) หากมีความคิดเห็นใด ๆ และมีแนวโน้มว่าจะมีก็ยินดีรับฟัง)
บทความก่อนหน้าของฉัน: |
---|
GO TO FULL VERSION