RPN Calculator Using Stacks - java

This is some code I got from my textbook which is a calculator solving expressions entered as postfix notation. I was wondering if there was a way I could keep using the stack instead of the stack restarting once the program evaluates an expression.
import java.util.Scanner;
import java.util.Stack;
public class RPN2
{
private Stack<Integer> stack;
public RPN2()
{
stack = new Stack<Integer>(); //creates stack
}
public static void main(String[] args)
{
String expression, again;
int result;
Scanner keyboard = new Scanner(System.in);
do
{
RPN2 evaluator = new RPN2();
System.out.println("Enter a valid post-fix expression one token " +
"at a time with a space between each token (e.g. 5 4 + 3 2 1 - + *)");
System.out.println("Each token must be an integer or an operator (+,-,*,/)");
expression = keyboard.nextLine();
result = evaluator.evaluate(expression);
System.out.println();
System.out.println("That expression equals " + result);
System.out.print("Evaluate another expression [Y/N]? ");
again = keyboard.nextLine();
System.out.println();
}
while (again.equalsIgnoreCase("y"));
}
public int evaluate(String expr)
{
int op1, op2, result = 0;
String token;
Scanner parser = new Scanner(expr);
while (parser.hasNext())
{
token = parser.next();
if (isOperator(token)) //if operator pop
{
op2 = (stack.pop()).intValue();
op1 = (stack.pop()).intValue();
result = evaluateSingleOperator(token.charAt(0), op1, op2); //
stack.push(new Integer(result));
}
else
stack.push(new Integer(Integer.parseInt(token)));
}
return result;
}
private boolean isOperator(String token)
{
return ( token.equals("+") || token.equals("-") ||
token.equals("*") || token.equals("/") || token.equals("%") );
}
private int evaluateSingleOperator(char operation, int op1, int op2)
{
int result = 0;
switch (operation)
{
case '+':
result = op1 + op2;
break;
case '-':
result = op1 - op2;
break;
case '*':
result = op1 * op2;
break;
case '/':
result = op1 / op2;
break;
case '%':
result = op1 % op2;
break;
}
return result;
}
}

Yes you can, see comments :
public RPN2() {
stack = new Stack<>(); //creates stack
}
void clearStack(){ //add clear stach method
stack.clear();
}
public static void main(String[] args)
{
String expression, again;
int result;
Scanner keyboard = new Scanner(System.in);
RPN2 evaluator = new RPN2(); //move out of the do loop
do
{
evaluator.clearStack();//use clear stack method
//rest of the code omitted (no change in it)

Related

RPN calculator with additional functions

I want to make the code use the stack class (stack of integers), together with a driver program which can handle the operations: 'm' unary minus -- negate the top item, 'r' exchange the top two items, 'd' duplicate top item on the stack, 'p' print (to the screen) the top item, n print and remove the top item, f print all the contents of the stack (leaving it intact), c clear the stack, 'q' quit, 'h' (or ?) print a help message.
import java.util.Scanner;
public class CalculatorDemo {
public static void main(String[] args)
{
String expression;
int result;
Scanner in = new Scanner(System.in);
do
{
calculator evaluator = new calculator();
System.out.println("Enter a valid post-fix expression one token " +
"at a time with a space between each token (e.g. 5 4 + 3 2 1 - + *)");
System.out.println("Each token must be an integer or an operator (+,-,*,/,%)for help(h/?)");
expression = in.nextLine();
result = evaluator.evaluate(expression);
System.out.println();
System.out.println(result);
}
while (result = 'q');
System.exit(0);
}
}
import java.util.*;
public class calculator
{
private Stack<Integer> stack;
public calculator()
{
stack = new Stack<Integer>();
}
public int evaluate(String expr)
{
int op1, op2, result = 0, help;
String key;
Scanner parser = new Scanner(expr);
while (parser.hasNext())
{
key = parser.next();
if (isOperator(key))
{
op2 = (stack.pop()).intValue();
op1 = (stack.pop()).intValue();
result = evaluateSingleOperator(key.charAt(0), op1, op2);
stack.push (new Integer(result));
}
else
stack.push(new Integer(Integer.parseInt(key)));
}
return result;
}
private boolean isOperator(String key)
{
return ( key.equals("+") || key.equals("-") ||
key.equals("*") || key.equals("/") ||
key.equals("h") || key.equals("?") ||
key.equals("p") || key.equals("n") ||
key.equals("d") || key.equals("r") ||
key.equals("c") || key.equals("f") ||
key.equals("%") || key.equals("m") ||
key.equals("q") );
}
private int evaluateSingleOperator(char operation, int op1, int op2)
{
int result = 0;
switch (operation)
{
case '+':
result = op1 + op2;
break;
case '-':
result = op1 - op2;
break;
case '*':
result = op1 * op2;
break;
case '/':
result = op1 / op2;
break;
case 'p':
result = op2;
break;
case '%':
result = op1 % op2;
break;
case 'm':
result = --op1;
break;
case'q':
result = (0);
break;
case'h'|'?':
int help = 0;
result = help;
break;
case 'r':
result = op1 ;//help
break;
case 'd':
result = op1;//help
break;
case 'n':
result = op1;//help
break;
case 'f':
result = op1;//help
break;
case 'c':
result = op1;//help
break;
}
return result;
}
private void help(String string) {
// TODO Auto-generated method stub
System.out.println("+ add the top two items" +
"* multiply the top two items" +
"- subtract the top item from the next item" +
"/ integer divide the second item by the top item" +
"% find the integer remainder when dividing the second item by the top item" +
"m unary minus -- negate the top item" +
"r exchange the top two items" +
"d duplicate top item on stack" +
"p print (to the screen) the top item" +
"n print and remove the top item" +
"f print all the contents of the stack (leaving it intact)" +
"c clear the stack" +
"q quit" +
"h (or ?) print a help message");
}
}

String equation answer in int form

I am in a low-level java class where I need to make an app using java and JavaScript. I have decided to create a game that creates a random equation using addition, subtraction, multiplication, and division. the trouble I am having is that my equation is created in the form of a string and I need to be able to calculate the answer to compare it to the users answer. I thought I had a descent solution to my issue but I keep getting some issues. can you help? my code is below:
import java.util.*;
public class GameClient {
private static Stack<String> operations;
private static Stack<Integer> numbers;
private static String[] tokens;
private static int i;
private static Stack<String> subAdd;
private static Stack<Integer> restOfNumbers;
public static void main(String[] args) {
Random variable = new Random();
int numberOfVariables = variable.nextInt(5)+2; //determines length of equation
String equation = "";
equation = equationGenerator(equation, numberOfVariables, variable);
System.out.println(equation);
System.out.print(calculateAnswer(equation));
}
public static String equationGenerator(String equation, int numberOfVariables, Random variable){
int operation;
int var;
var = variable.nextInt(10)+1;
equation += var;
operation = variable.nextInt(4)+1;
if(numberOfVariables == 1){
equation += " = ";
return equation;
}
if(operation == 1)
{
equation += " + ";
}
else if(operation == 2)
{
equation += " - ";
}
else if(operation == 3)
{
equation += " / ";
}
else if(operation == 4)
{
equation += " * ";
}
return equationGenerator(equation, numberOfVariables-1, variable);
}
public static int calculateAnswer(String equation){
String delims = "[ ]+";
tokens = equation.split(delims);
for(i=0; i< tokens.length; i++) //does all multiplication and division first leaving just addition and subtraction
switch(tokens[i]){
case "0": case "1":case "2":case "3":case "4":case "5":case "6":case "7":case "8":case "9":
int number = Integer.parseInt(tokens[i]);
popOrPush(number);
break;
case "*": case "/": case "+": case "-":
popOrPush(tokens[i], tokens);
}
while(!numbers.empty()){ //flips number and operation stacks to do addition and subtraction in correct order
restOfNumbers.push(numbers.pop());
}
while(!operations.empty()){
subAdd.push(operations.pop());
}
while(!subAdd.empty()){
switch(subAdd.pop()){
case "+":
restOfNumbers.push(restOfNumbers.pop() + restOfNumbers.pop());
case "-":
restOfNumbers.push(restOfNumbers.pop() - restOfNumbers.pop());
}
}
return restOfNumbers.pop();
}
public static void popOrPush(int number){
numbers.push(number);
}
public static void popOrPush(String operation, String[] tokens){
switch(operation){
case "*":
int multipliedValue = numbers.pop();
i++;
multipliedValue = multipliedValue * Integer.parseInt(tokens[i]);
numbers.push(multipliedValue);
case "/":
int dividedValue = numbers.pop();
i++;
dividedValue = dividedValue / Integer.parseInt(tokens[i]);
numbers.push(dividedValue);
case "+": case "-":
operations.push(operation);
}
}
}
You're not initializing your Stack, so you're likely getting a NPE when trying to use the numbers variable.
Make sure to initialize all of your variables (particularly your Stack objects). For example:
Stack<Integer> numbers = new Stack<>();

How can i separate two data types in user input?

I am creating a calculator in which a user will directly input the numbers and the operator...
Here is my code:
int answer = 0;
int num1, num2;
char operator;
System.out.print("Enter calculation: ");
num1 = kb.nextInt();
operator = kb.next().charAt(0);
num2 = kb.nextInt();
The code above will accept the user input when there are spaces like this:
1 + 1
so the program will give an answer which is 2.
But if i input 1+1 it will give an error
Exception in thread "main" java.util.InputMismatchException
How can i do that it will separate integer to character? because i set the operator as character. So that it will accept one digit to several digit numbers. Like 500+84 or 1520/872, 30*5, 148-65?
I don't have much experience with the java.util.Scanner class. But, I suspect that it tokenizes on a well-defined token separator, such as spaces, tabs, a comma, pipe characters, etc. So, this may be a poor choice in tokenizing your type of input.
To successfully tokenize your type of input, I suggest implementing a proper lexical analyzer. This may be overkill here (like using a tank to hunt a rabbit), but to do it properly and formally with some guarantee of success, you would need to write a lexical analyzer. The web is chock-full of examples of writing a lexical analyzer. For your input, it may look something like this:
public class Scanners {
public static void main(String args[]) {
Lexer lexer = new Lexer("32221-8 +45 ");
for(String token : lexer)
System.out.println("token = "+token);
}
private static final class Lexer implements Iterable<String> {
private int pos=0;
private final String input;
private final int inputLength;
private String token;
public Lexer(String input) {
this.input = input;
this.inputLength = input.length();
advance();
}
private void advance() {
if(pos>=inputLength) {
token = null;
return;
}
char c = input.charAt(pos++);
if(Character.isDigit(c))
token = advanceNumber(c);
else if(Character.isJavaIdentifierStart(c))
token = advanceVariable(c);
else if(Character.isWhitespace(c)) {
advanceWhitespace();
advance();
} else
// here, assuming a one-character operator
token = Character.toString(c);
}
private String advanceNumber(char c) {
StringBuilder sb = new StringBuilder().append(c);
while(pos<inputLength) {
c = input.charAt(pos);
if(Character.isDigit(c)) {
sb.append(c);
++pos;
} else
break;
}
return sb.toString();
}
private String advanceVariable(char c) {
StringBuilder sb = new StringBuilder().append(c);
while(pos<inputLength) {
c = input.charAt(pos);
if(Character.isJavaIdentifierPart(c)) {
sb.append(c);
++pos;
} else
break;
}
return sb.toString();
}
private void advanceWhitespace() {
while(pos<inputLength && Character.isWhitespace(input.charAt(pos)))
++pos;
}
#Override
public Iterator<String> iterator() {
return new Iterator<String>() {
#Override
public boolean hasNext() {
return token != null;
}
#Override
public String next() {
String retval = token;
advance();
return retval;
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
}
}
// output
// ------
// token = 32221
// token = -
// token = 8
// token = +
// token = 45
It does not expect negative operands. It throws an exception if a number is too big. It does not explain what the "error in expression" is. So there's plenty of room for improvement.
Scanner scn = new Scanner( System.in );
Pattern pat = Pattern.compile( "\\s*(\\d+)\\s*([-+*/])\\s*(\\d+)\\s*" );
while( scn.hasNextLine() ){
String line = scn.nextLine();
Matcher mat = pat.matcher( line );
if( mat.matches() ){
int op1 = Integer.parseInt( mat.group(1) );
char od = mat.group(2).charAt(0);
int op2 = Integer.parseInt( mat.group(3) );
System.out.println( op1 + " " + od + " " + op2 );
} else {
System.out.println( "error in expression" );
}
}
This is a simpler version. Similar caveats apply here, too. Moreover, it throws an exception on invalid numbers and accepts almost anything as an operator.
Scanner scn = new Scanner( System.in );
scn.useDelimiter( "\\b|\\s+" );
while( scn.hasNextLine() ){
int op1 = scn.nextInt();
char od = scn.next().charAt(0);
int op2 = scn.nextInt();
System.out.println( op1 + " " + od + " " + op2 );
scn.nextLine();
}
Try using 3 scanner?
Scanner scn = new Scanner(System.in);
int operand1, operand2;
String operator;
operand1 = Integer.parseInt(scn.next());
operator = scn.next();
operand2 = Integer.parseInt(scn.next());
OP changes his question I left.
I was away just now after I posted this solution. Didn't have time to improve it. Now I give you a better and simple solution:
I supposed you do not expect user to input things like "12+45*67/20" right? Assuming there will be two operands.
1) Receive input as 1 whole string
2) Trim all the spaces from the input
3) Split string into tokens of integers
Scanner scn = new Scanner(System.in);
String[] token = new String[12];
System.out.print("Enter equation:");
String input = scn.nextLine().trim();
String operator = "";
double answer=0, operand1=0, operand2=0;
if (input.indexOf("+") != -1){
token = input.split("\\+");
operator = "+";
}
else if (input.indexOf("-") != -1){
token = input.split("-");
operator = "-";
}
else if (input.indexOf("*") != -1){
token = input.split("\\*");
operator = "*";
}
else if (input.indexOf("/") != -1){
token = input.split("/");
operator = "/";
}
else
System.out.println("Invalid equation!");
if(token[0].matches("[0-9]+") && token[1].matches("[0-9+]"))
{
operand1 = Double.parseDouble(token[0]);
operand2 = Double.parseDouble(token[1]);
switch (operator)
{
case "+": answer = operand1 + operand2;
break;
case "-": answer = operand1 - operand2;
break;
case "*": answer = operand1 * operand2;
break;
case "/": answer = operand1 / operand2;
break;
}
}
System.out.println(answer);
Just copy and paste the whole thing to test it, it will work.
You can do it like this:
Scanner scn = new Scanner(System.in);
Integer operand1, operand2;
char operator;
System.out.println("Enter first operand: ");
operand1 = scn.nextInt();
System.out.println("Enter operator: ");
operator = scn.next().charAt(0);
System.out.println("Enter second operand: ");
operand2 = scn.nextInt();

I can't make my PostFix Evaluator work correctly

I have no clue what I am supposed to be doing here, but I think I have most of my code good. I can only edit code inside the Evaluate() method. Pls help.
Here is my class with my main method
package labs.lab3;
import java.util.Scanner; // Needed for the Scanner
import java.io.*; // Needed for the File and IOException
public class TestDriver {
/**
* #param args
*/
public static void main(String[] args) throws IOException {
System.out.printf("%-30s", "Postfix Expression");
System.out.printf("%-30s", "Evaluation Result");
System.out.println();
String filename = "./src/labs/lab3/PostfixExpressions.txt";
File file = new File(filename);
Scanner inputFile = new Scanner(file);
while (inputFile.hasNext())
{
String expression = inputFile.nextLine();
System.out.printf("%-30s", expression);
PostfixEvaluator evaluator = new PostfixEvaluator(expression);
System.out.printf("%-30s" , evaluator.Evaluate());
System.out.println();
}
inputFile.close();
}
}
And Here is my Post Fix Evaluator class:
package labs.lab3;
import java.util.Stack;
import java.util.EmptyStackException;
import java.util.StringTokenizer;
public class PostfixEvaluator
{
private Stack<Integer> stack;
private String expression;
private String token;
public PostfixEvaluator(String e)
{
stack = new Stack<Integer>();
expression = e;
}
// Evaluate the postfix expression and return the evaluation result
public int Evaluate()
{
int op1,op2;
int result;
StringTokenizer st = new StringTokenizer(expression);//split the expression into tokens
String token=st.nextToken();
while (st.hasMoreTokens()){
if (Character.isDigit(token.charAt(0))) {
int value = Integer.parseInt(token);
stack.push(value);
}
else if (!Character.isDigit(token.charAt(0))) {
op1=stack.pop();
op2=stack.pop();
result = Calculate(op1,op2,token.charAt(0));
stack.push(result);
}
}
int answer = stack.pop();
return answer;
}
// Perform an operation on the two operands
public int Calculate(int operand1, int operand2, char operation)
{
int result = 0;
switch (operation)
{
case '+':
result = operand1 + operand2;
break;
case '-':
result = operand1 - operand2;
break;
case '/':
result = operand1 / operand2;
break;
case '*':
result = operand1 * operand2;
break;
case '%':
result = operand1 % operand2;
break;
}
return result;
}
}
Thanks
I can't see you move forward in the tokenizer. You call nextToken just
once, outside the loop. The rest of the code seems to indicate that evaluate
should consume the entire expression, So nextToken needs to be called inside
the loop.

Can't detect 2 digit numbers when converting from RPN to Infix

i am trying to implement a java method which accepts an input in RPN (Reverse Polish Notation) and through use of a stack converts it into an infix notation and calculates it. I have built the stack and a working converter but i am finding problems when it comes to accepting multiple digit numbers (such as 10), my idea to solve this was to enter each separate entity separated by a space, 10+20 would be entered as "10 20 +" but this is resulting in an out of bounds error. Without the section marked below the program works fine for equations such as "12+" (1+2) and more complex ones as long as they involve single digit values. The stack is fully functiopnal too with push and pop methods
public static void stackRPN(){
Stack myStack = new Stack();
Scanner sc = new Scanner(System.in);
System.out.println("Enter an equation: ");
String eq = sc.nextLine();
int len = eq.length();
for (int i = 0; i < len; i++){
String car1 = String.valueOf(eq.charAt(i));
if ("+".equals(car1) || "-".equals(car1) || "/".equals(car1) || /*"car1"*/"x".equals(car1)){
String a = myStack.pop();
String b = myStack.pop();
//This handlws all the digits
double bI = Double.parseDouble(b);
double aI = Double.parseDouble(a);
double finalNo = 0;
switch (car1) {
case "+": finalNo = bI + aI;
break;
case "-": finalNo = bI - aI;
break;
case "/": finalNo = bI / aI;
break;
case "x": finalNo = bI * aI;
break;
}
myStack.push(finalNo+"");
String finEq = b+car1+a;
System.out.println(finEq + " = " +finalNo);
} else {
This bit does not work
while (len < i+1 && eq.charAt(i+1) != ' '){
car1 = car1+eq.charAt(i+1);
i++;
}
Till here
myStack.push(car1);
}
}
mainMenu();
}
This was fixed using the split method in the string class as so
public static void stackRPN(){
Stack myStack = new Stack();
Scanner sc = new Scanner(System.in);
System.out.print("Enter an equation: ");
System.out.println();
String eq = sc.nextLine();
//This Bit splits up the string where it meets a space
String[] eqS = eq.split(" ");
int len = eqS.length;
for (int i = 0; i < len; i++){
String car1 = eqS[i];
if ("+".equals(car1) || "-".equals(car1) || "/".equals(car1) || /*"car1"*/"x".equals(car1)){
String a = myStack.pop();
String b = myStack.pop();
//This handlws all the digits
double bI = Double.parseDouble(b);
double aI = Double.parseDouble(a);
double finalNo = 0;
switch (car1) {
case "+": finalNo = bI + aI;
break;
case "-": finalNo = bI - aI;
break;
case "/": finalNo = bI / aI;
break;
case "x": finalNo = bI * aI;
break;
}
myStack.push(finalNo+"");
String finEq = b+car1+a;
System.out.println(finEq + " = " +finalNo);
} else {
myStack.push(car1);
}
}
mainMenu();
}

Categories