Search code examples
javalistqueuestackjgroups

Is there a way to solve or fix the codes of my Exercise20_23.java for Revel?


I'm trying to make that Exercise20_23.java work but it is not working.

I tried this;

import java.util.*;

public class Exercise20_23 {
   public static void main(String[] args) {
      Scanner scanner = new Scanner(System.in);
      System.out.print("Enter an expression: ");
      String expression = scanner.nextLine();
      
      try {
         System.out.println(expression + " = " + evaluateExpression(expression));
      }
      catch (Exception ex) {
         System.out.println("Wrong expression: " + expression);
      }
   }
     
   /** Evaluate an expression */
   public static int evaluateExpression(String expression) {
      // Create operandStack to store operands
      Stack<Integer> operandStack = new Stack<>();
    
      // Create operatorStack to store operators
      Stack<Character> operatorStack = new Stack<>();
    
      // Insert blanks around (, ), +, -, /, *, ^, and %
      expression = insertBlanks(expression);
   
      // Extract operands and operators
      String[] tokens = expression.split(" ");
   
      // Phase 1: Scan tokens
      for (String token: tokens) {
         if (token.length() == 0) // Blank space
            continue; // Back to the for loop to extract the next token
         else if (token.charAt(0) == '+' || token.charAt(0) == '-') {
            // Process all +, -, *, /, ^. % in the top of the operator stack 
            while (!operatorStack.isEmpty() &&
               (operatorStack.peek() == '+' || 
                operatorStack.peek() == '-' ||
                operatorStack.peek() == '*' ||
                operatorStack.peek() == '/' ||
                operatorStack.peek() == '^' ||
                operatorStack.peek() == '%')) {
               processAnOperator(operandStack, operatorStack);
            }
         
            // Push the + or - operator into the operator stack
            operatorStack.push(token.charAt(0));
         }
         else if (token.charAt(0) == '*' || token.charAt(0) == '/' || token.charAt(0) == '%') {
            // Process all *, /, % in the top of the operator stack 
            while (!operatorStack.isEmpty() &&
               (operatorStack.peek() == '*' ||
                operatorStack.peek() == '/' ||
                operatorStack.peek() == '%' )) {
               processAnOperator(operandStack, operatorStack);
            }
         
            // Push the *, /, or % operator into the operator stack
            operatorStack.push(token.charAt(0));
         }
         else if (token.charAt(0) == '^') {
            // Process all ^ in the top of the operator stack 
            while (!operatorStack.isEmpty() &&
               (operatorStack.peek() == '^')) {
               processAnOperator(operandStack, operatorStack);
            }
         
            // Push the ^ operator into the operator stack
            operatorStack.push(token.charAt(0));
         }
         else if (token.trim().charAt(0) == '(') {
            operatorStack.push('('); // Push '(' to stack
         }
         else if (token.trim().charAt(0) == ')') {
            // Process all the operators in the stack until seeing '('
            while (operatorStack.peek() != '(') {
               processAnOperator(operandStack, operatorStack);
            }
            
            operatorStack.pop(); // Pop the '(' symbol from the stack
         }
         else { // An operand scanned
            // Push an operand to the stack
            operandStack.push(Integer.valueOf(token));
         }
      }
   
      // Phase 2: Process all the remaining operators in the stack 
      while (!operatorStack.isEmpty()) {
         processAnOperator(operandStack, operatorStack);
      }
   
      // Return the result
      return operandStack.pop();
   }

   /** Process one operator: Take an operator from operatorStack and
    *  apply it on the operands in the operandStack */
   public static void processAnOperator(Stack<Integer> operandStack, Stack<Character> operatorStack) {
      char op = operatorStack.pop();
      int op1 = operandStack.pop();
      int op2 = operandStack.pop();
      if (op == '+') 
         operandStack.push(op2 + op1);
      else if (op == '-') 
         operandStack.push(op2 - op1);
      else if (op == '*') 
         operandStack.push(op2 * op1);
      else if (op == '/') 
         operandStack.push(op2 / op1);
      else if (op == '^') 
         operandStack.push((int)Math.pow(op2, op1));
      else if (op == '%') 
         operandStack.push(op2 % op1);
   }
   
   public static String insertBlanks(String s) {
      String result = "";
      
      for (int i = 0; i < s.length(); i++) {
         if (s.charAt(i) == '(' || s.charAt(i) == ')' || 
              s.charAt(i) == '+' || s.charAt(i) == '-' ||
              s.charAt(i) == '*' || s.charAt(i) == '/' ||
              s.charAt(i) == '^' || s.charAt(i) == '%')
            result += " " + s.charAt(i) + " ";
         else
            result += s.charAt(i);
      }
      
      return result;
   }
   
   /*
   OUTPUT:
       
   ----jGRASP exec: java --module-path C:\Users\rmeri\Downloads\openjfx-19_windows-x64_bin-sdk\javafx-sdk-19\lib --add-modules=javafx.controls Exercise20_23
  Enter an expression: (5 * 2 ^ 3 + 2 * 3 % 2) * 4
  (5 * 2 ^ 3 + 2 * 3 % 2) * 4 = 160
  
   ----jGRASP: operation complete.
  
   ----jGRASP exec: java --module-path C:\Users\rmeri\Downloads\openjfx-19_windows-x64_bin-sdk\javafx-sdk-19\lib --add-modules=javafx.controls Exercise20_23
  Enter an expression: 349 % 23 ^ 2 + 4 ^ 4 % 5
  349 % 23 ^ 2 + 4 ^ 4 % 5 = 605
  
   ----jGRASP: operation complete.
  
   
   */
}

And I tried this;

import java.util.*;

public class Exercise20_23 {
  public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);
    System.out.print("Enter an expression: ");
    String expression = scanner.nextLine();
    String temp = expression;
    
    try {
      System.out.println(expression + " = " + evaluateExpression(expression));
    }
    catch (Exception ex) {
      System.out.println("Wrong expression: " + temp);
    }
  }
    
  /** Evaluate an expression */
  public static int evaluateExpression(String expression) {
    // Create operandStack to store operands
    Stack<Integer> operandStack = new Stack<>();
  
    // Create operatorStack to store operators
    Stack<Character> operatorStack = new Stack<>();
  
    // Insert blanks around (, ), +, -, /, *, ^, and %
    expression = insertBlanks(expression);

    // Extract operands and operators
    String[] tokens = expression.split(" ");

    // Phase 1: Scan tokens
    for (String token: tokens) {
      if (token.length() == 0) // Blank space
        continue; // Back to the for loop to extract the next token
      else if (token.charAt(0) == '+' || token.charAt(0) == '-') {
        // Process all +, -, *, /, ^. % in the top of the operator stack 
        while (!operatorStack.isEmpty() &&
          (operatorStack.peek() == '+' || 
           operatorStack.peek() == '-' ||
           operatorStack.peek() == '*' ||
           operatorStack.peek() == '/' ||
           operatorStack.peek() == '^' ||
           operatorStack.peek() == '%')) {
          processAnOperator(operandStack, operatorStack);
        }

        // Push the + or - operator into the operator stack
        operatorStack.push(token.charAt(0));
      }
      else if (token.charAt(0) == '*' || token.charAt(0) == '/' || token.charAt(0) == '%') {
        // Process all *, /, % in the top of the operator stack 
        while (!operatorStack.isEmpty() &&
          (operatorStack.peek() == '*' ||
           operatorStack.peek() == '/' ||
           operatorStack.peek() == '%' )) {
          processAnOperator(operandStack, operatorStack);
        }

        // Push the *, /, or % operator into the operator stack
        operatorStack.push(token.charAt(0));
      }
      else if (token.charAt(0) == '^') {
        // Process all ^ in the top of the operator stack 
        while (!operatorStack.isEmpty() &&
          (operatorStack.peek() == '^')) {
          processAnOperator(operandStack, operatorStack);
        }

        // Push the ^ operator into the operator stack
        operatorStack.push(token.charAt(0));
      }
      else if (token.trim().charAt(0) == '(') {
        operatorStack.push('('); // Push '(' to stack
      }
      else if (token.trim().charAt(0) == ')') {
        // Process all the operators in the stack until seeing '('
        while (operatorStack.peek() != '(') {
          processAnOperator(operandStack, operatorStack);
        }
        
        operatorStack.pop(); // Pop the '(' symbol from the stack
      }
      else { // An operand scanned
        // Push an operand to the stack
        operandStack.push(Integer.valueOf(token));
      }
    }

    // Phase 2: Process all the remaining operators in the stack 
    while (!operatorStack.isEmpty()) {
      processAnOperator(operandStack, operatorStack);
    }

    // Return the result
    return operandStack.pop();
  }

  /** Process one operator: Take an operator from operatorStack and
   *  apply it on the operands in the operandStack */
  public static void processAnOperator(Stack<Integer> operandStack, Stack<Character> operatorStack) {
    char op = operatorStack.pop();
    int op1 = operandStack.pop();
    int op2 = operandStack.pop();
    if (op == '+') 
      operandStack.push(op2 + op1);
    else if (op == '-') 
      operandStack.push(op2 - op1);
    else if (op == '*') 
      operandStack.push(op2 * op1);
    else if (op == '/') 
      operandStack.push(op2 / op1);
    else if (op == '^') 
      operandStack.push((int)Math.pow(op2, op1));
    else if (op == '%') 
      operandStack.push(op2 % op1);
    else if (op != '(' || op != ')') {
    if (op == '%') 
      operandStack.push(op2 % op1);
    else if (op == '^') 
      operandStack.push((int)Math.pow(op2, op1));
    else if (op == '+') 
      operandStack.push(op2 + op1);
    else if (op == '-') 
      operandStack.push(op2 - op1);
    else if (op == '*') 
      operandStack.push(op2 * op1);
    else if (op == '/') 
      operandStack.push(op2 / op1);
   }
  }
  
  public static String insertBlanks(String s) {
    String result = "";
    
    for (int i = 0; i < s.length(); i++) {
      if (s.charAt(i) == '(' || s.charAt(i) == ')' || 
          s.charAt(i) == '+' || s.charAt(i) == '-' ||
          s.charAt(i) == '*' || s.charAt(i) == '/' ||
          s.charAt(i) == '^' || s.charAt(i) == '%')
        result += " " + s.charAt(i) + " ";
      else
        result += s.charAt(i);
    }
    
    return result;
  }
  
  /*
  OUTPUT:
  
  ----jGRASP exec: java --module-path C:\Users\rmeri\Downloads\openjfx-19_windows-x64_bin-sdk\javafx-sdk-19\lib --add-modules=javafx.controls Exercise20_23
 Enter an expression: (5 * 2 ^ 3 + 2 * 3 % 2) * 4
 (5 * 2 ^ 3 + 2 * 3 % 2) * 4 = 160
 
  ----jGRASP: operation complete.
 
  ----jGRASP exec: java --module-path C:\Users\rmeri\Downloads\openjfx-19_windows-x64_bin-sdk\javafx-sdk-19\lib --add-modules=javafx.controls Exercise20_23
 Enter an expression: 349 % 23 ^ 2 + 4 ^ 4 % 5
 349 % 23 ^ 2 + 4 ^ 4 % 5 = 605
 
  ----jGRASP: operation complete.
 
  */
}

But both codes didn't the result I'm looking for, according to this linkPlease click the link here to see the correct output] (https://i.sstatic.net/Jk2hu.png)

I'm trying to modify the Evaluate Expression into adding '^', '%' chars for operators so I can complete the revel project but I don't know what else to I need to do, so if anyone can tell me what's wrong with both of those codes above, I will really appreciate it.


Solution

  • You're close.

    I see you're using jGRASP, and debugging these kinds of problems is what it is made for. Set a breakpoint at the first statement inside the main loop (the "if" statement) and debug. From the "Variables" tab, drag out the operator and operand stacks and drop them anywhere. This will pop up "viewers" so that you can watch the stacks as they fill up and empty. You can also open a canvas and drag both variables there for convenience as shown in the image below (you can save the canvas for later reuse, unlike individual viewers). Hit "resume" on the debugger repeatedly and watch the stacks along with the "token" variable (which you could also drag onto a canvas for convenience) which at that point in the code will be the "next" token to be processed. Compare what is happening on the stacks to what should be happening based on precedence, like (349 % (23 ^ 2)) + ((4 ^ 4) % 5). When you spot the operator that causes the problem, quit and restart the debugger, resume until the problem point, then use the debugger "step" and/or "step in" button to go line-by-line until you see the cause.

    enter image description here