Advertisement
Sanlover

Solver.java

Nov 21st, 2021
1,447
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 7.28 KB | None | 0 0
  1. package ser;
  2. import java.util.ArrayList;
  3. import java.util.Collections;
  4.  
  5. /**
  6.  * Класс, котрый вычисляет результат выражения записанного строкой
  7.  * <p>
  8.  *
  9.  * @author Лера Былдина
  10.  * @version 1.0
  11.  * @since 1.0
  12.  */
  13. public class Solver {
  14.     /**
  15.      *  Символы, воспринимающиеся операторами внутри программы
  16.      */
  17.     private final char[] kOperators = {'+','-','*','/'};
  18.  
  19.     /**
  20.      * Возвращает массив [x,x...x,x] длинной с количество символов в строке с выражением
  21.      * каждый элемент - число, показывающее насколько глубоко *в слоях скобочек* зарыто число
  22.      * так, строка "1+4*(5-6*(3+2)+4)+0" будет иметь глубину:
  23.      *             [0000111112222211100]
  24.      *
  25.      * @param expr - строка с выражением
  26.      * @return ArrayList<Integer> - массив глубин
  27.      */
  28.     private ArrayList<Integer> getDepth(String expr) {
  29.         ArrayList<Integer> depth = new ArrayList<Integer>(Collections.nCopies(expr.length(), 0));
  30.         int depthLevel = 0;
  31.         for (int i = 0; i < expr.length(); i++) {
  32.             if (expr.charAt(i) == '(') {
  33.                 depthLevel++;
  34.                 depth.set(i, depthLevel);
  35.             } else if (expr.charAt(i) == ')') {
  36.                 depth.set(i, depthLevel);
  37.                 depthLevel--;
  38.             } else {
  39.                 depth.set(i, depthLevel);
  40.             }
  41.         }
  42.         return depth;
  43.     }
  44.  
  45.     /**
  46.      * Убирает скобочки, меняя при этом массив глубин (понижает
  47.      * глубину всех элементов и удаляет последний первый глубины
  48.      * т.к. удалены первая скобочка и последняя)
  49.      *
  50.      * @param expr - строка с выражением
  51.      * @param depth - массив глубин
  52.      * @return String - строка без скобочек
  53.      */
  54.     private String fitExpression(ArrayList<Integer> depth, String expr) {
  55.         for (int i = 0 ; i < depth.size() ; i++) {
  56.             depth.set(i,depth.get(i)-1);
  57.         }
  58.         expr = expr.substring(1, expr.length() - 1);
  59.         depth.remove(depth.size()-1);
  60.         depth.remove(0);
  61.         return expr;
  62.     }
  63.  
  64.     /**
  65.      * Проверяет,есть ли хотя бы один оператор в строке с выражением
  66.      *
  67.      * @param expr - строка с выражением
  68.      * @return boolean - true, если в строке найден хотя бы один оператор, иначе false
  69.      */
  70.     private boolean hasOperator(String expr) {
  71.         for (char kOperator : kOperators) {
  72.             if (expr.indexOf(kOperator) != -1) {
  73.                 return true;
  74.             }
  75.         }
  76.         return false;
  77.     }
  78.  
  79.     /**
  80.      * Проверяет,есть ли хотя бы один оператор в строке с выражением на 0 уровне
  81.      *
  82.      * @param expr - строка с выражением
  83.      * @return boolean - true, если в строке найден хотя бы один оператор на 0 уровне, иначе false
  84.      */
  85.     private boolean hasFirstFloorOperator(String expr,
  86.                                           ArrayList<Integer> depth) {
  87.         for (int i = 0; i < expr.length(); i++) {
  88.             if (depth.get(i) == 0) {
  89.                 for (char kOperator : kOperators) {
  90.                     if (expr.charAt(i) == kOperator) {
  91.                         return true;
  92.                     }
  93.                 }
  94.             }
  95.         }
  96.         return false;
  97.     }
  98.  
  99.     /**
  100.      * Чистить строку от пробелов и вызывает рекурсивную функцию, которая
  101.      * решает выражение, путём разложения на левую и правую части от операторов
  102.      * на 0 уровне
  103.      *
  104.      * @param expr - строка с выражением
  105.      * @return double - результат выражения
  106.      */
  107.     public double calculate(String expr){
  108.         expr = expr.replaceAll("\\s","");
  109.         return calculate_method(expr,getDepth(expr));
  110.     }
  111.  
  112.     /**
  113.      * Рекурсивная функция, внутри которой происходит деление на две части:
  114.      * левую и правую, от найденного в ней оператор. Елси оператор не был найден
  115.      * то это ситуация, когда в строк осталось только число, и мы возвращаем
  116.      * Double.parseDouble от строки. Если же оператор в строке был найден, но на 0 уровне
  117.      * не нашлось, то мы в ситуации, когда всё выражение находится в скобках, тогда
  118.      * мы убираем скобки и понижаем глубину строки
  119.      *
  120.      * @param expr - строка с выражением
  121.      * @param depth - массив глубин строки
  122.      * @return double - результат выражения
  123.      */
  124.     private double calculate_method(String expr, ArrayList<Integer> depth) {
  125.         if (!hasOperator(expr)) {
  126.             return Double.parseDouble(expr);
  127.         }
  128.         while (!hasFirstFloorOperator(expr, depth)) {
  129.             expr = fitExpression(depth, expr);
  130.         }
  131.         String l = null, r = null;
  132.         int operatorId = 0;
  133.         boolean isFound = false;
  134.         for (int k = 0; k < kOperators.length && !isFound; k++) {
  135.             if (expr.indexOf(kOperators[k]) != -1) {
  136.                 int operatorPos = 0;
  137.  
  138.                 for (int j = 0; j < kOperators.length && !isFound; j++) {
  139.                     for (int i = 0; i < expr.length() && !isFound; i++) {
  140.                         if (depth.get(i) == 0) {
  141.                             if (expr.charAt(i) == kOperators[j]) {
  142.                                 operatorPos = i;
  143.                                 operatorId = j;
  144.                                 isFound = true;
  145.                             }
  146.                         }
  147.                     }
  148.                 }
  149.  
  150.                 l = expr.substring(0, operatorPos);
  151.                 r =
  152.                         expr.substring(operatorPos + 1);
  153.             }
  154.         }
  155.         switch (operatorId) {
  156.             case 0 -> {
  157.                 return calculate_method(l, getDepth(l)) +
  158.                         calculate_method(r, getDepth(r));
  159.             }
  160.             case 1 -> {
  161.                 return calculate_method(l, getDepth(l)) -
  162.                         calculate_method(r, getDepth(r));
  163.             }
  164.             case 2 -> {
  165.                 return calculate_method(l, getDepth(l)) *
  166.                         calculate_method(r, getDepth(r));
  167.             }
  168.             case 3 -> {
  169.                 return calculate_method(l, getDepth(l)) /
  170.                         calculate_method(r, getDepth(r));
  171.             }
  172.         }
  173.         return 0.0;
  174.     }
  175. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement