I am writing an evaluation code for polish notation. When I overcome ClassCastException I get EmptyStack and when I solve Emptystack I get ClassCast I'm in a loop.
Here is how I wanted to evaluate the Polish notation:
First I get a string from the user then put it into a stack. For evaluating I use a second stack. Why?
Because:
An example string: "* + * + 1 2 + 3 4 5 6" First operation here is to add up 3 and 4 but what I'm gonna do with 5 and 6? I put them in another stack. Let's say stack2. I start popping until I found an operator, in this condition I pushed 6 5 4 3 into stack2 and found a plus operator. Then I pop 2 numbers which I pushed to stack2 (the top 2 numbers are 3 and 4), add them up, and push them to stack again.
I should evaluate but seems like I am missing a point or this wasn't a good idea at first.
Here is my code:
public class Main {
public static void stack(String srt){ // this function puts the string in srt stack
String arr[] = srt.split(" "); // I am recognizing if there is a 2 or more digit number
int size= arr.length; // with receiving prefix with " " btw every number and operator
Stack stack= new Stack();
for (String s : arr) {
// System.out.println(s);
stack.push(s);
}
// for (int i = 0; i < size; i++) {
// System.out.println(stack.pop()); // I checked to see if any
// problems first now I dont start this
// }
evaluate(stack); // then calls the evaluate function
}
public static void evaluate(Stack stack){
Stack stack2= new Stack();
stack2.push(stack.pop());// cuz of there cant be an operator there I pop first 2 number
stack2.push(stack.pop());
for (int i = 0; i < (stack.capacity()*2); i++) { // I had a hard time calculating how many times
// I should cycle through this for and leave it 2 times as stack capacity
if(stack.peek().toString().equals("*") || stack.peek().toString().equals("-") || stack.peek().toString().equals("/") || stack.peek().toString().equals("+")){
System.out.println("Checkpoint1");
// System.out.println(stack2.peek());
int s2= Integer.parseInt((String) stack2.pop());
int s1= Integer.parseInt((String) stack2.pop());
double s3;
String c = (String) stack.pop();
switch (c) {
case "+":
s3=s1+s2;
stack2.push(s3);
case "-":
s3=s1-s2;
stack2.push(s3);
case "*":
s3=s1*s2;
stack2.push(s3);
case "/":
s3=s1/s2;
stack2.push(s3);
}
}else{
System.out.println("Checkpoint 2");
stack2.push(Integer.parseInt((String) stack.pop()));
// System.out.println(stack.peek());
}
}
// System.out.println(stack.peek());
// System.out.println(stack2.peek());
}
public static void main(String[] args) {
String examplestr ="* + * + 1 2 + 3 4 5 6";
stack(examplestr);
}
}
Thank you for your help!!!
So turns out the switch-case doesn't operate correctly because I forgot a fundamental part "break". For EmptyStackException, I made a try-catch and put them inside so when it returns empty stack I know evaluation is done and print the result. BUT I still don't know how to deal with these little problems. It feels like I did not solve them properly. Gotta work more. Thanks.
Edit: I made some more adjustments and this is my final working code. I couldn't detect an error in the results yet.
Here is the working code;
import java.util.EmptyStackException;
import java.util.Stack;
public class Main2 {
public static void stack(String srt) {
String arr[] = srt.split(" ");
int size = arr.length;
Stack stack = new Stack();
for (int i = 0; i < size; i++) {
if (arr[i].toString().equals("*") || arr[i].toString().equals("-") || arr[i].toString().equals("/") || arr[i].toString().equals("+"))
stack.push(arr[i]);
else
stack.push(Double.parseDouble(arr[i]));
}
// for (int i = 0; i < size; i++) {
// System.out.println(stack.pop());
// }
evaluate(stack);
}
public static void evaluate(Stack stack) {
Stack stack1 = new Stack();
stack1.push(stack.pop());
stack1.push(stack.pop());
for (int i = 0; i < stack1.capacity(); i++) {
try {
if (stack.peek().toString().equals("*") || stack.peek().toString().equals("-") || stack.peek().toString().equals("/") || stack.peek().toString().equals("+")) {
// System.out.println("Checkpoint1");
double s1 = (double) stack1.pop();
double s2 = (double) stack1.pop();
double s3;
String operator = String.valueOf(stack.pop());
switch (operator) {
case "+":
s3 = s1 + s2;
stack1.push(s3);
break;
case "-":
s3 = s1 - s2;
stack1.push(s3);
break;
case "*":
s3 = s1 * s2;
stack1.push(s3);
break;
case "/":
s3 = s1 / s2;
stack1.push(s3);
break;
}
} else {
// System.out.println("Checkpoint 2");
stack1.push(Double.parseDouble(String.valueOf(stack.pop())));
}
} catch (EmptyStackException e) {
System.out.println("Notasyonun sonucu: " + stack1.peek());
}
}
}
public static void main(String[] args) {
String notasyon = scanner.nextLine();
stack(notasyon);
}
}
Related
private Scanner sc = new Scanner(System.in);
private String expression;
private String exp[];
private ArrayList<String> post_fix = new ArrayList<>();
Stack<String> ope = new Stack<String>();
public Model()
{
expression = sc.nextLine();
}
public void split()
{
//splitting the entered expression to array of operators alone and array of the numbers then create Arraylist to combine the operators and numbers together as if it is a string expression but as an array
String num[]= this.expression.split("[/+/*/-]");
String preop[]= this.expression.split("[0-9]+");; // this will give [empty, operator, operator...] therefore we will create another array to fill in the ops excluding empty
ArrayList<String> op = new ArrayList<>();//I used arraylist because easier
for(int i = 1; i<preop.length;i++)
{
op.add(preop[i]);
}
//putting the operands and the operators together in the same array
ArrayList<String> exp = new ArrayList<>();
for(int i = 0; i <num.length;i++)
{
exp.add(num[i]);
}
int count = 0;
for(int i = 0; i <op.size();i++)
{ //fill the arraylist with numbers then add the operators to it by using number (index of the operator +1 +count)
exp.add(i+1+count, op.get(i)); //This is why arraylist was used in order to let values to be placed in between
count++;
//i+1+count is used because index of the operator is in between two numbers meaning it is after the first index in num array so i+1 and because array keeps increasing, we do +count for the other operators to be placed in
}
this.exp = new String[exp.size()]; // we change the arraylist exp to instance array for faster operations later on
System.out.print("Test to check if expression is converted into array as intented: ");
for(int i = 0; i<this.exp.length;i++)
{
this.exp[i] = exp.get(i);
System.out.print(this.exp[i]);
}
System.out.println();
}
public void postfix()
{
for(int i = 0; i < exp.length; i++)
{
if(i%2 == 0)//since operands are observed to always have even index in the array
{
post_fix.add(exp[i]);
System.out.println(post_fix);
}
else
{
boolean x = !ope.empty();
System.out.println("Test of !ope.empty: " + x);
while(!ope.empty()&& HasHigherPrecedence(ope.peek(), this.exp[i]))
{
post_fix.add(ope.peek());
ope.pop();
}
ope.push(exp[i]);
System.out.println("stack_top: "+ ope.peek());
}
}
while(!ope.empty())
{
post_fix.add(ope.peek());
ope.pop();
}
System.out.println("Output: " +post_fix);
}
public String getPost_fix()
{
String temp = "";
for(int i =0; i < exp.length;i++)
{
temp = temp + post_fix.get(i);
}
return temp;
}
public double evaluate()
{
return 0;
}
private boolean HasHigherPrecedence(String op1, String op2)
{
//op1 is operator 1 at the top of the stack thus associativity highest
int a_op1 = 1;
int a_op2 = 0;
int p_op1 = 0;
int p_op2= 0;
//the precedence will be measured with numbers
String operators[]= {"","+","-","*","/"};
int precedence[] = {0,1,1,2,2}; //the reason for blank operator and 0 precedence is because the stack initially will be empty
for(int i = 0; i< operators.length;i++)
{
if(op1.equals(operators[i]))
{
p_op1=precedence[i];
}
}
for(int i = 0; i< operators.length;i++)
{
if(op2.equals(operators[i]))
{
p_op2=precedence[i];
}
}
boolean higher_ornot = false;
if(p_op1 > p_op2)
{
higher_ornot = false;
}
else if(p_op1 < p_op1)
{
higher_ornot = true;
}
else if(p_op1== p_op2)
{
System.out.println(op1+": "+p_op1);
System.out.println(op2+": "+p_op2);
higher_ornot = false; //since associativity of op1 will be higher --> thus higher precedence
}
return higher_ornot;
}
}
I am trying to converst user's infix mathmatical expression into a postfix expression in an array that will be evaluated but before evaluation, I faced a problem in the postfix method
while(!ope.empty()&& HasHigherPrecedence(ope.peek(), this.exp[i]))
This specific line is not being called out when the condition should be true, when it is comparing top of the stack which is * to - and * has higher precedence and since stack is not empty thus it should return true thus the function is called. I tested if I have any errors other areas but everything I tested was correct, I really have no clue how to fix.
I am really clueless even after 1hour and a half staring and trying to trace the code
I am expecting from output to be
[3, 2, 4, *, +, 3, -] which is the postfix expression that technically will be evaluated later
I am working on a project to convert infix notation to postfix notation and then evaluate the equation. I established the precedence for each operator. When I use the ConvertToPostfix method I get the Exception. I understand the concept of the reverse polish notation calculator and I am just struggling with doing it with my code. I am new to stack overflow so if there is something that may seem a little confusing just let me know and ill try to edit it.
import java.util.Stack;
public class RPNCalctest {
public static void main( String[] args) throws InvalidInfixEquationException {
String example= "3+4/3*2"; //postfix notation would be 3 4 3 / 2 * +
System.out.println(ConvertToPostfix(example));
// TODO
}
//establish precedence
static int precedence(String c){
switch(c){
case"+":
case"-":
return 1;
case"*":
case"/":
return 2;
case")":
return 3;
case"(":
return 4;
default:
return -1;
}
}
// Precondition: every operator/operand will be separated by at least one space
public static String ConvertToPostfix(String infix) throws InvalidInfixEquationException {
String[] tokens = infix.split(" ");
String result = "";
Stack<String> stack = new Stack<>();
for (int i = 0; i < tokens.length; i++) {
String current = tokens[i];
if (precedence(current) > 0) {
while (!stack.isEmpty() && precedence(stack.peek()) >= precedence(current)) {
result += stack.pop() + " ";
}
stack.push(current);
} else {
result += current + " ";
}
}
for (int i = 0; i <= stack.size(); i++) {
result += stack.pop();
}
return result;
}
}
Exception in thread "main" java.util.EmptyStackException
at java.base/java.util.Stack.peek(Stack.java:101)
at java.base/java.util.Stack.pop(Stack.java:83)
at RPNCalctest.ConvertToPostfix(RPNCalctest.java:50)
at RPNCalctest.main(RPNCalctest.java:7)
Your problem is here. You pop off one more entry than there is.
for (int i = 0; i <= stack.size(); i++) {
result += stack.pop();
}
Consider size=2. You execute the loop for i=0, 1, 2.
I assume that the 'pop' line is line 53 as indicated in the stack trace, so for future reference, that's useful debugging info and you should use it.
It might be clearer if that loop were coded:
while (!stack.isEmpty()) {
result += stack.pop();
}
No need for the extraneous variable 'i'.
In relation to my last question about setting the TextView as the method output this question is about splitting the integer into separate digits. My Roman Numeral program works by using the translator method here:
'public static String translator(int integer) {
String result = "";
LinkedList<String> stack = new LinkedList<String>();
// if (integer > 0 && integer <= 4999) {
//ArrayList<Integer> placement = new ArrayList<Integer>();
int place = (int) Math.log10(integer);
for (int i = 0; i <= place; i++) {
//while(integer > 0){
//System.out.println(integer);
int placeOfValue = integer % 10;
//stack.push(placeOfValue);
//System.out.print(stack);
//System.out.print(placeOfValue +":" + i);
String placement = "";
switch (i) {
case 0:
placement = ones(placeOfValue);
break;
case 1:
placement = tens(placeOfValue);
break;
case 2:
placement = hundreds(placeOfValue);
break;
case 3:
placement = thousands(placeOfValue);
break;
default:
break;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
stack.push(placement);
}
integer = integer / 10;
//System.out.print(placement);
// System.out.println(placement.size());
//}
// for(int j = 0; j < placement.size(); j++){
// double tenthPower = Math.floor(Math.log10(placement.get(j)));
// double place = Math.pow(10, tenthPower);
// System.out.println(place);
//
// }
// }
while (!stack.isEmpty()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
result += stack.pop();
//System.out.print(stack.pop());
}
}
// } else {
// System.out.println("Please enter an integer between 0 and 4,999.");
// }
}
return result;
}
`
The translator method works by going through the for loop which will loop through the size of the integer then assigning the digit a given placement. From the placement it will then look through the placement methods and return the numeral. Since the integers are added in reverse for the LinkedList I have pushed the stack and popped it based on this post How to get the separate digits of an int number? to get the correct order. However the program continues to print out the numerals in reverse order which is not what I want. I have debugged the program but with no luck it feels like something is off with the pop method and adding it to the output but I can't figure out what.
I ended up solving this problem by uncommenting out a bracket which separated the stack.push() from the stack.pop(). After that the rest of the code works!
I'm trying to create a method that would create an equation for me, as a String.
For example, this method would create:
String formula = "5 + 3";
then another method will solve it.
I don't really know how to create the string. Should i use concat?
Thanks for all the help.
public static String getEquation() {
for(int i=0;i<7;i++){
int rand = rng.nextInt(5);
switch (rand) {
case 0:
operator = "+";
break;
case 1:
operator = "-";
break;
case 2:
operator = "*";
break;
case 3:
operator = "/";
break;
case 4:
operator = "(";
break;
case 5:
operator = ")";
}
}
return formula;
}
Wrote something up really quick, I think this should get you going. You'd have to handle the cases for parentheses though. I didn't account for that.
import java.util.Random;
public class Test {
static Random randomGenerator = new Random();
static String operators = "+-*/P"; //p = parentheses pair
public static char getRandomOperator() {
return operators.charAt(randomGenerator.nextInt(operators.length()));
}
public static int getRandomNumber() {
return randomGenerator.nextInt(100);
}
public static String createEquation() {
//Just for proof of concept, let's do 3 operators
String equation = "";
int numOfOperators = 3;
char operator = ' ';
for (int i = 0; i < numOfOperators; i++) {
equation += getRandomNumber();
equation += getRandomOperator();
}
equation += getRandomNumber();
return equation;
}
public static void main(String[] args) {
String equation = createEquation();
System.out.println(equation);
}
}
I may have time later and come back and address the parentheses issue. For now I just print 'P' where parentheses should be handled.
EDIT
Updated it to handle parentheses. I'm going to paste it down here in case you want to keep it as the old way. Also did a couple tweaks here and there. Note that I didn't handle it matching an exact number of operators when it comes to parenthesis. Which means that if all the open parenthesis weren't closed by the time the loop is done grabbing operators then I append extra parenthesis at the end. Which can result in more than 7 operators. You should probably add logic to either treat a pair of parenthesis as 1 operator or 1 parenthesis as a single operator. Enjoy.
import java.util.Random;
public class Test {
static Random randomGenerator = new Random();
static String operators = "+-*/()";
static int opeatorStringLength = operators.length();
public static char getRandomOperator() {
return operators.charAt(randomGenerator.nextInt(opeatorStringLength));
}
public static int getRandomNumber() {
return randomGenerator.nextInt(100);
}
public static String appendToEquation(String equation, String value1, String value2) {
String temp = equation;
temp += value1;
temp += value2;
return temp;
}
public static String createEquation(int numOfOperators) {
String equation = "";
char operator;
int operand;
int openParenCounter = 0;
for (int i = 0; i < numOfOperators; i++) {
operator = getRandomOperator();
operand = getRandomNumber();
if (operator == '(') {
openParenCounter++;
equation = appendToEquation(equation, Character.toString(operator), Integer.toString(operand));
} else if (operator == ')') {
if (openParenCounter == 0) { //Can't start off with a close parenthesis
openParenCounter++;
equation = appendToEquation(equation, "(", Integer.toString(operand));
} else {
openParenCounter--;
equation = appendToEquation(equation, Integer.toString(operand), Character.toString(operator));
}
} else {
equation = appendToEquation(equation, Integer.toString(operand), Character.toString(operator));
}
}
equation += getRandomNumber();
while (openParenCounter > 0) {
equation += ")";
openParenCounter--;
}
return equation;
}
public static void main(String[] args) {
String equation;
equation = createEquation(7); //The argument passed is the number of operators to use
System.out.println(equation);
}
}
Hey Guys I'm having a problem when I run my program. In the PostfixEvaluate() Method is where it takes in a string and solves the postfix problem and returns it. Well when I go to run it, I'm getting a bunch of random numbers(some repeated), I'm going crazy because I don't know what else to try and I've spent more time on this than it should normally take.
Heres the PostfixEvaluate Method:
public int PostfixEvaluate(String e){
//String Operator = "";
int number1;
int number2;
int result=0;
char c;
//number1 = 0;
//number2 = 0;
for(int j = 0; j < e.length(); j++){
c = e.charAt(j);
if (c != '+'&& c!= '*' && c!= '-' && c!= '/') {
//if (c == Integer.parseInt(e)) {
s.push(c);
}
else {
number1 = s.pop();
number2 = s.pop();
switch(c) {
case '+':
result = number1 + number2;
break;
case '-':
result = number1 - number2;
break;
case '*':
result = number1 * number2;
break;
case '/':
result = number1 / number2;
break;
} s.push(result);
}
System.out.println(result);
}
return s.pop();
}
public static void main(String[] args) {
Stacked st = new Stacked(100);
String y = new String("(z * j)/(b * 8) ^2");
String x = new String("2 3 + 9 *");
TestingClass clas = new TestingClass(st);
clas.test(y);
clas.PostfixEvaluate(x);
}
}
This is the Stack Class:
public class Stacked {
int top;
char stack[];
int maxLen;
public Stacked(int max) {
top = -1;
maxLen = max;
stack = new char[maxLen];
}
public void push(int result) {
top++;
stack[top] = (char)result;
}
public int pop() {
int x;
x = stack[top];
//top = top - 1;
top--;
return x;
}
public boolean isStackEmpty() {
if(top == -1) {
System.out.println("Stack is empty " + "Equation Good");
return true;
}
else
System.out.println("Equation is No good");
return false;
}
public void reset() {
top = -1;
}
public void showStack() {
System.out.println(" ");
System.out.println("Stack Contents...");
for(int j = top; j > -1; j--){
System.out.println(stack[j]);
}
System.out.println(" ");
}
public void showStack0toTop() {
System.out.println(" ");
System.out.println("Stack Contents...");
for(int j=0; j>=top; j++){
System.out.println(stack[j]);
}
System.out.println(" ");
}
}
It looks to me like you aren't handling spaces at all.
This means that when you put in a space, it is implicitly converting the character space to the ascii value of it (32) when it pops it off the stack during an operation. Also, it looks like you are assuming that all numbers/results will be single digit, and casting from char to int, which is not what you want to do, since that will convert the char to the ascii value of the char, ' ' -> 32, '3' -> 51, etc.
If I were you, I would do this for your loop in PostfixEvaluate:
while(!e.equals("")){
string c;
int space = e.indexOf(' ');
if(space!=-1){
c = e.substring(0,space);
e = e.substring(space+2);
} else{
c = e;
e = "";
}
if (!c.equals("+")&& !c.equal("*") && !c.equals("-") && !c.equals("/")) {
//...
}
and change your stack to hold strings or ints.
The problem is that you are pushing char onto a stack as an int, so you are unintentionally working with the ascii representations of numbers, which is not the actual value of the number.
Instead of this complicated character walking, tokenize the input string using String.split(). Example:
String[] tokens = e.split(" ");
for(String token:tokens){
if (!"+".equals(token) && !"*".equals(token) && !"-".equals(token) && !"/".equals(token)) {
s.push(Integer.parseInt(token));
} else {
....
}
}
You need to split the string into tokens first:
/* Splits the expression up into several Strings,
* all of which are either a number or and operator,
* none of which have spaces in them. */
String [] expressionAsTokens = e.split(" ");
Then you need to make sure you compare Strings, not chars:
//compare strings instead of chars
String token = expressionAsTokens[j];
if (!"+".equals(token) && !"*".equals(token) && !"-".equals(token) && !"/".equals(token)) {
s.push(Integer.parseInt(token));
} else {
//same code as you had before
}
Also, is there any reason you are storing everything as a char array in your Stacked class? Your pop() method returns and integer, yet everything is stored as a char.
For this application, everything should be stored as an integer:
public class Stacked {
int stack[]; // array is of type integer
int top;
int maxLen;
// constructor
public void push() {/*...*/}
public int pop() {/*...*/} //pop returns an int as before
//...
}
One final note: Be careful what order you add and subtract the numbers in. I don't remember if postfix operands are evaluated left first or right first, but make sure you get them in the right order. As you have it now, 2 3 - 4 * would evaluate as 4 * (3 - 2) and I think it should be (2 - 3) * 4. This won't matter with adding and multiplying, but it will with subtracting and dividing.