Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package ser;
- import java.util.ArrayList;
- import java.util.Collections;
- /**
- * Класс, котрый вычисляет результат выражения записанного строкой
- * <p>
- *
- * @author Лера Былдина
- * @version 1.0
- * @since 1.0
- */
- public class Solver {
- /**
- * Символы, воспринимающиеся операторами внутри программы
- */
- private final char[] kOperators = {'+','-','*','/'};
- /**
- * Возвращает массив [x,x...x,x] длинной с количество символов в строке с выражением
- * каждый элемент - число, показывающее насколько глубоко *в слоях скобочек* зарыто число
- * так, строка "1+4*(5-6*(3+2)+4)+0" будет иметь глубину:
- * [0000111112222211100]
- *
- * @param expr - строка с выражением
- * @return ArrayList<Integer> - массив глубин
- */
- private ArrayList<Integer> getDepth(String expr) {
- ArrayList<Integer> depth = new ArrayList<Integer>(Collections.nCopies(expr.length(), 0));
- int depthLevel = 0;
- for (int i = 0; i < expr.length(); i++) {
- if (expr.charAt(i) == '(') {
- depthLevel++;
- depth.set(i, depthLevel);
- } else if (expr.charAt(i) == ')') {
- depth.set(i, depthLevel);
- depthLevel--;
- } else {
- depth.set(i, depthLevel);
- }
- }
- return depth;
- }
- /**
- * Убирает скобочки, меняя при этом массив глубин (понижает
- * глубину всех элементов и удаляет последний первый глубины
- * т.к. удалены первая скобочка и последняя)
- *
- * @param expr - строка с выражением
- * @param depth - массив глубин
- * @return String - строка без скобочек
- */
- private String fitExpression(ArrayList<Integer> depth, String expr) {
- for (int i = 0 ; i < depth.size() ; i++) {
- depth.set(i,depth.get(i)-1);
- }
- expr = expr.substring(1, expr.length() - 1);
- depth.remove(depth.size()-1);
- depth.remove(0);
- return expr;
- }
- /**
- * Проверяет,есть ли хотя бы один оператор в строке с выражением
- *
- * @param expr - строка с выражением
- * @return boolean - true, если в строке найден хотя бы один оператор, иначе false
- */
- private boolean hasOperator(String expr) {
- for (char kOperator : kOperators) {
- if (expr.indexOf(kOperator) != -1) {
- return true;
- }
- }
- return false;
- }
- /**
- * Проверяет,есть ли хотя бы один оператор в строке с выражением на 0 уровне
- *
- * @param expr - строка с выражением
- * @return boolean - true, если в строке найден хотя бы один оператор на 0 уровне, иначе false
- */
- private boolean hasFirstFloorOperator(String expr,
- ArrayList<Integer> depth) {
- for (int i = 0; i < expr.length(); i++) {
- if (depth.get(i) == 0) {
- for (char kOperator : kOperators) {
- if (expr.charAt(i) == kOperator) {
- return true;
- }
- }
- }
- }
- return false;
- }
- /**
- * Чистить строку от пробелов и вызывает рекурсивную функцию, которая
- * решает выражение, путём разложения на левую и правую части от операторов
- * на 0 уровне
- *
- * @param expr - строка с выражением
- * @return double - результат выражения
- */
- public double calculate(String expr){
- expr = expr.replaceAll("\\s","");
- return calculate_method(expr,getDepth(expr));
- }
- /**
- * Рекурсивная функция, внутри которой происходит деление на две части:
- * левую и правую, от найденного в ней оператор. Елси оператор не был найден
- * то это ситуация, когда в строк осталось только число, и мы возвращаем
- * Double.parseDouble от строки. Если же оператор в строке был найден, но на 0 уровне
- * не нашлось, то мы в ситуации, когда всё выражение находится в скобках, тогда
- * мы убираем скобки и понижаем глубину строки
- *
- * @param expr - строка с выражением
- * @param depth - массив глубин строки
- * @return double - результат выражения
- */
- private double calculate_method(String expr, ArrayList<Integer> depth) {
- if (!hasOperator(expr)) {
- return Double.parseDouble(expr);
- }
- while (!hasFirstFloorOperator(expr, depth)) {
- expr = fitExpression(depth, expr);
- }
- String l = null, r = null;
- int operatorId = 0;
- boolean isFound = false;
- for (int k = 0; k < kOperators.length && !isFound; k++) {
- if (expr.indexOf(kOperators[k]) != -1) {
- int operatorPos = 0;
- for (int j = 0; j < kOperators.length && !isFound; j++) {
- for (int i = 0; i < expr.length() && !isFound; i++) {
- if (depth.get(i) == 0) {
- if (expr.charAt(i) == kOperators[j]) {
- operatorPos = i;
- operatorId = j;
- isFound = true;
- }
- }
- }
- }
- l = expr.substring(0, operatorPos);
- r =
- expr.substring(operatorPos + 1);
- }
- }
- switch (operatorId) {
- case 0 -> {
- return calculate_method(l, getDepth(l)) +
- calculate_method(r, getDepth(r));
- }
- case 1 -> {
- return calculate_method(l, getDepth(l)) -
- calculate_method(r, getDepth(r));
- }
- case 2 -> {
- return calculate_method(l, getDepth(l)) *
- calculate_method(r, getDepth(r));
- }
- case 3 -> {
- return calculate_method(l, getDepth(l)) /
- calculate_method(r, getDepth(r));
- }
- }
- return 0.0;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement