Java Algorithm for Evaluating Expressions - java

I'm trying to implement this pseudo-code in java, to evaluate an arithmetic expression. But I keep getting the last digit: ie if i do 1+2, i'd just get 2; I don't know what I'm doing incorrectly, so If anyone has any idea, please let me know!!
Algorithm here
import java.util.Stack;
public class Main {
static Stack<String> ops = new Stack<String>();
static Stack<Double> vals = new Stack<Double>();
private static void doOP() {
double x = vals.pop();
double y = vals.pop();
String op = ops.pop();
double v = 0;
if (op.equals("+")) {
v = y + x;
} else {
if (op.equals("-")) {
v = y - x;
} else {
if (op.equals("*")) {
v = y * x;
} else {
if (op.equals("/")) {
v = y / x;
}
}
}
}
vals.push(v);
}
private static void repeatOps(String refOp) {
while ((vals.size() > 1) && (prec(refOp) <= prec(ops.peek()))) {
doOP();
}
}
private static int prec(String refOp) {
String[] bodmas = new String[] { "(", ")", "/", "*", "+", "-", "$" };
int i = 0;
for (String operation : bodmas) {
if (refOp.equals(operation)) {
return i;
}
i++;
}
return -0;
}
private static boolean isNumber(String number) {
try {
#SuppressWarnings("unused")
double d = Double.parseDouble(number);
} catch (Exception e) {
return false;
}
return true;
}
private static Double evalExp(String exp) {
for (char z : exp.toCharArray()) {
if (isNumber(z + "")) {
vals.push(Double.parseDouble(z + ""));
} else {
repeatOps(z + "");
ops.push(z + "");
}
}
repeatOps("$");
return vals.peek();
}
public static void main(String[] args) {
System.out.println(evalExp("3*2"));
}
}

Your prec() method is inverted and incorrect.
$ should be lowest precedence, meaning lowest value, e.g. 0.
+ and - should have same precedence.
* and / should have same precedence.
( and ) are not binary operators, and cannot be handled with the described logic.
So, fix prec to return 0 for $, 1 for + and -, and 2 for * and /.

Related

Can't get replace to work

I am making a program that will help me convert DFA to a regular expression using an algorithm we learned at the course.
CODE:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Collections;
import java.util.regex.Pattern;
import java.util.Arrays;
import java.io.*;
public class DFK {
static ArrayList<Path> done = new ArrayList<Path>();
public static void print() {
for(Path i: done) {
System.out.println("NOT REPLACED: "+ i);
if(i.isConverted()) {
System.out.println("WITH REPLACE: "+ i.getConverted()+"\n");
} else
System.out.print("\n");
}
}
public static void develop() {
if(done.get(0).getKP1() > 0) {
DFK.add(new Path(done.get(0).getP(), done.get(0).getQ(), done.get(0).getK()));
DFK.add(new Path(done.get(0).getP(), done.get(0).getKP1(), done.get(0).getK()));
DFK.add(new Path(done.get(0).getKP1(), done.get(0).getKP1(), done.get(0).getK()));
DFK.add(new Path(done.get(0).getKP1(), done.get(0).getQ(), done.get(0).getK()));
}
}
public static void add(Path x) {
boolean exists = (done.indexOf(x)==-1 ? false : true);
if(exists == false) {
done.add(x);
if(x.getKP1() >= 2) {
DFK.add(new Path(x.getP(), x.getQ(), x.getK()));
DFK.add(new Path(x.getP(), x.getKP1(), x.getK()));
DFK.add(new Path(x.getKP1(), x.getKP1(), x.getK()));
DFK.add(new Path(x.getKP1(), x.getQ(), x.getK()));
}
}
}
public static void main(String argv[]) throws IOException {
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
int p = 0, q = 0, kp1 = 0;
Scanner in = new Scanner(System.in);
System.out.print("p = ");p = in.nextInt();
System.out.print("q = ");q = in.nextInt();
System.out.print("k+1 = ");kp1 = in.nextInt();
System.out.print("\n");
String rkzero[][] = new String[q][q];
for(int i=0; i<q ; i++) {
for(int j=0; j<q ; j++) {
System.out.print(String.format("r(%d,%d,0): ", i+1, j+1));
rkzero[i][j]=input.readLine();
}
}
done.add(new Path(p, q, kp1));
DFK.develop();
Collections.sort(done);
for(int z=0; z<q ; z++) {
for(int j=0; j<q ; j++) {
for(Path i: done)
if(i.getKP1()==1) {
String reg = String.format("r(%d,%d,0)",z+1,j+1); //
i.setConverted(i.toString().replace( reg , rkzero[z][j])); //HERE IS THE PROBLEM I THINK
}
}
}
System.out.print("\n");
DFK.print();
}
}
class Path implements Comparable<Path> {
int p,q,kplus1,k;
String converted = null;
public int getP() {
return p;
}
public int getQ() {
return q;
}
public int getKP1() {
return kplus1;
}
public int getK() {
return k;
}
public Path(int a, int b, int c) {
super();
p = a;
q = b;
kplus1 = c;
k = c-1;
}
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (!Path.class.isAssignableFrom(obj.getClass())) {
return false;
}
final Path other = (Path) obj;
if(other.p == this.p && other.q == this.q && other.kplus1 == this.kplus1)
return true;
return false;
}
public int compareTo(Path other) {
return other.kplus1-kplus1;
}
public String toString() {
return String.format("r(%d,%d,%d)=r(%d,%d,%d)+r(%d,%d,%d)r(%d,%d,%d)*r(%d,%d,%d)",p,q,kplus1,p,q,k,p,kplus1,k,kplus1,kplus1,k,kplus1,q,k);
}
public void setConverted(String x) {
converted = new String(x);
}
public String getConverted() {
return converted;
}
public boolean isConverted() {
if(converted == null)
return false;
return true;
}
}
CURRENT OUTPUT:
p = 1
q = 2
k+1 = 2
r(1,1,0): 0
r(1,2,0): 1
r(2,1,0): 1
r(2,2,0): 0
NOT REPLACED: r(1,2,2)=r(1,2,1)+r(1,2,1)r(2,2,1)*r(2,2,1)
NOT REPLACED: r(1,2,1)=r(1,2,0)+r(1,1,0)r(1,1,0)*r(1,2,0)
WITH REPLACE: r(1,2,1)=r(1,2,0)+r(1,1,0)r(1,1,0)*r(1,2,0)
NOT REPLACED: r(2,2,1)=r(2,2,0)+r(2,1,0)r(1,1,0)*r(1,2,0)
WITH REPLACE: r(2,2,1)=0+r(2,1,0)r(1,1,0)*r(1,2,0)
WANTED OUTPUT:
p = 1
q = 2
k+1 = 2
r(1,1,0): 0
r(1,2,0): 1
r(2,1,0): 1
r(2,2,0): 0
NOT REPLACED: r(1,2,2)=r(1,2,1)+r(1,2,1)r(2,2,1)*r(2,2,1)
NOT REPLACED: r(1,2,1)=r(1,2,0)+r(1,1,0)r(1,1,0)*r(1,2,0)
WITH REPLACE: r(1,2,1)=1+00*1
NOT REPLACED: r(2,2,1)=r(2,2,0)+r(2,1,0)r(1,1,0)*r(1,2,0)
WITH REPLACE: r(2,2,1)=0+10*1
As you can see it only replaces r(2,2,0) with 0, and nothing else and I cant find out why. I replicated the problem in a previous question, but it turned out there was a non-ascii comma in my code there which caused the issue, but here I can't find it.
I used grep --color='auto' -P -n "[^\x00-\x7F]" DFK.java and it didn't find any non ascii characters, so I hope it's not the same problem.
The program should iterate over all Paths that have kplus1 = 1 and replace all r(i,j,0) with strings I have previously entered. Keep in mind, it is not finished yet.
The mistake is I was using toString to get the string in which I replace things, and so I replace one string and for the next replacement I use the original string again and thus throwing away the last replacement and so on.
So the solution is to make converted initialize as the same string as toString() inside constructor:
converted = String.format("r(%d,%d,%d)=r(%d,%d,%d)+r(%d,%d,%d)r(%d,%d,%d)*r(%d,%d,%d)",p,q,kplus1,p,q,k,p,kplus1,k,kplus1,kplus1,k,kplus1,q,k);
and then in main use:
i.setConverted( i.getConverted().replace(reg, rkzero[z][j]) );
so I save the intermediate solution in converted.

How to rewrite my toPostfix() method to use isOperator()?

In my program I am working on converting from infix to postfix. I have a method named isOperator(), which will return true if the precedance of the operator is greater than 0.
I am supposed to rewrite the toPostfix() method using isOperator(), but I am unsure where to begin.
public class Expression {
private static final String SPACE = " ";
private static final String PLUS = "+";
private static final String MINUS = "-";
public static int rank(String operator) {
switch (operator) {
case "*":
case "/":
return 2;
case PLUS:
case MINUS: //2
return 1;
default:
return -1;
}
}
public static boolean isOperator(String token) { //4
if (rank(token) > 0){
return true;
}
return false;
}
public static String toPostfix(String infixExpr) {
StringBuilder output = new StringBuilder();
Stack<String> operators = new ArrayStack<>();
for (String token: infixExpr.split("\\s+")) {
if (rank(token) > 0) { // operator
// pop equal or higher precedence
while (!operators.isEmpty() &&
rank(operators.peek()) >= rank(token)) {
output.append(operators.pop() + SPACE);
}
operators.push(token);
} else { // operand
output.append(token + SPACE);
}
}
while (!operators.isEmpty()) {
output.append(operators.pop() + SPACE);
}
return output.toString();
}
public static void main(String[] args) {
System.out.println(rank("/"));
String infix = "a * b * c + d / e / f";
System.out.println(toPostfix(infix));
}
}
Change if(rank(token) > 0){ in your postfix method to isOperator(token)
Change: if(rank(token) > 0){
To: isOperator(token)

Calculator, can't get it to print out as I want it

This is a homework of mine. However, I can't get the result to work. I want it to print out as:
> 2*7*6
2
* 7
----
14
* 6
----
84
and so on. I want the code to work regardless of how many numbers I type in. This is my code so far;
public static int add(int a, int b) {
return a + b;
}
public static int sub(int a, int b) {
return a - b;
}
public static int multiply(int a, int b) {
return a * b;
}
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
System.out.print("(ex. 8*2*6): ");
String amount = in.nextLine();
if ( amount.contains("+") ) {
String[] parts = amount.split("\\+");
} else if ( amount.contains("-") ) {
String[] parts = amount.split("\\-");
} else if ( amount.contains("*") ) {
String[] parts = amount.split("\\*");
int[] results = new int[parts.length];
// Convert from string to integer
for (int i = 0; i < parts.length; i++) {
try {
results[i] = Integer.parseInt(parts[i]);
} catch (NumberFormatException nfe) {};
}
// Print result
int counter = 1;
for (int i = 0; i <= results.length; i++) {
if ( i == 0) {
System.out.println(" " + results[i]);
System.out.println("* " + results[counter]);
System.out.println("----");
int total = multiply(results[i], results[counter]);
System.out.println(" " + total);
} else if ( i > 1 ) {
System.out.println("* " + results[i]);
System.out.println("----");
System.out.println(" " + multiply(results[i], results[counter]) );
}
}
} else {
System.out.println("Error");
}
What am I doing wrong?
Is not c# isn it? I'm not sure if i understand you.
In c#, have you tried something like that.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args) {
// Scanner in = new Scanner(System.in);
// String amount = Console.ReadLine();
String amount = "2*7*6*5*3*2";
if (amount.Contains('+')) {
String[] parts = amount.Split('+');
}
else
if (amount.Contains('-')) {
String[] parts = amount.Split('-');
}
else if (amount.Contains("*")) {
String[] parts = amount.Split('*');
int[] results = new int[parts.Length];
// Convert from string to integer
for (int i = 0; i < parts.Length; i++) {
try {
results[i] = int.Parse(parts[i]);
}
catch (FormatException nfe) { };
}
// Print result
int total = results[0];
for (int i = 1; i < results.Length; i++) {
if (i == 1)
Console.WriteLine(" " + results[i - 1]);
Console.WriteLine("* " + results[i]);
Console.WriteLine("----");
total = multiply(results[i], total);
Console.WriteLine(" " + total);
}
}
else {
Console.WriteLine("Error");
}
Console.ReadKey();
}
public static int add(int a, int b) {
return a + b;
}
public static int sub(int a, int b) {
return a - b;
}
public static int multiply(int a, int b) {
return a * b;
}
public static void main(String[] args) {
}
}
}

Math Expression Parser

I found the code of Math Expression Parser from Dreamincode Forum.
My question is, on that code I think everything is going all right, but when I had a testcase '(2(3+5)' , that was valid, whereas this test case is completely wrong
but if I give the test case '(3+5)2)' it was detect as non valid input.
Anyone knows why this is happening?
//enum for Operator "objects"
import java.util.*;
public enum Operator {
ADD("+", 1)
{
double doCalc(double d1, double d2) {
return d1+d2;
}
},
SUBTRACT("-",1)
{
double doCalc(double d1, double d2) {
return d1-d2;
}
},
MULTIPLY("*", 2)
{
double doCalc(double d1, double d2) {
return d1*d2;
}
},
DIVIDE("/",2)
{
double doCalc(double d1, double d2) {
return d1/d2;
}
},
STARTBRACE("(", 0)
{
double doCalc(double d1, double d2) {
return 0;
}
},
ENDBRACE(")",0)
{
double doCalc(double d1, double d2) {
return 0;
}
},
EXP("^", 3)
{
double doCalc(double d1, double d2) {
return Math.pow(d1,d2);
}
};
private String operator;
private int precedence;
private Operator(String operator, int precedence) {
this.operator = operator;
this.precedence = precedence;
}
public int getPrecedenceLevel() {
return precedence;
}
public String getSymbol() {
return operator;
}
public static boolean isOperator(String s) {
for(Operator op : Operator.values()) { //iterate through enum values
if (op.getSymbol().equals(s))
return true;
}
return false;
}
public static Operator getOperator(String s)
throws InvalidOperatorException {
for(Operator op : Operator.values()) { //iterate through enum values
if (op.getSymbol().equals(s))
return op;
}
throw new InvalidOperatorException(s + " Is not a valid operator!");
}
public boolean isStartBrace() {
return (operator.equals("("));
}
//overriding calculation provided by each enum part
abstract double doCalc(double d1, double d2);
}
//error to be thrown/caught in ProjectOne.java
class InvalidOperatorException extends Exception {
public InvalidOperatorException() {
}
public InvalidOperatorException(String s) {
super(s);
}
}
//reading in a string at doing the parsing/arithmetic
public static void main (String[] args) {
String input = "";
//get input
System.out.print("Enter an infix exp<b></b>ression: ");
BufferedReader in = new BufferedReader(
new InputStreamReader(System.in));
try {
input = in.readLine();
}
catch (IOException e)
{
System.out.println("Error getting input!");
}
doCalculate(input);
}
// Input: user entered string
// Output: Display of answer
public static void doCalculate(String equation) {
//our stacks for storage/temp variables
Stack<Operator> operatorStack;
Stack<Double> operandStack;
double valOne, valTwo, newVal;
Operator temp;
//initalize
StringTokenizer tokenizer = new StringTokenizer(equation, " +-*/()^", true);
String token = "";
operandStack = new Stack();
operatorStack = new Stack();
try {
while(tokenizer.hasMoreTokens()){ //run through the string
token = tokenizer.nextToken();
if (token.equals(" ")) { //handles spaces, goes back up top
continue;
}
else if (!Operator.isOperator(token)){ //number check
operandStack.push(Double.parseDouble(token));
}
else if (token.equals("(")) {
operatorStack.push(Operator.getOperator(token));
}
else if (token.equals(")")) { //process until matching paraentheses is found
while (!((temp = operatorStack.pop()).isStartBrace())) {
valTwo = operandStack.pop();
valOne = operandStack.pop();
newVal = temp.doCalc(valOne, valTwo);
operandStack.push(newVal);
}
}
else { //other operators
while (true) { //infinite loop, check for stack empty/top of stack '('/op precedence
if ((operatorStack.empty()) || (operatorStack.peek().isStartBrace()) ||
(operatorStack.peek().getPrecedenceLevel() < Operator.getOperator(token).getPrecedenceLevel())) {
operatorStack.push(Operator.getOperator(token));
break; //exit inner loop
}
temp = operatorStack.pop();
valTwo = operandStack.pop();
valOne = operandStack.pop();
//calculate and push
newVal = temp.doCalc(valOne, valTwo);
operandStack.push(newVal);
}
}
}
}
catch (InvalidOperatorException e) {
System.out.println("Invalid operator found!");
}
//calculate any remaining items (ex. equations with no outer paraentheses)
while(!operatorStack.isEmpty()) {
temp = operatorStack.pop();
valTwo = operandStack.pop();
valOne = operandStack.pop();
newVal = temp.doCalc(valOne, valTwo);
operandStack.push(newVal);
}
//print final answer
System.out.println("Answer is: " + operandStack.pop());
}
This calculator does not work with implicit multiplication. you can use:
2((2+2)+1)
And see that it gives the wrong answer as opposed to:
2*((2+2)+1)
The false-positive expression you've used does not pass with explicit multiplication.
A quick for-the-lazy fix to add implicit multiplication would be something of that sort:
public static void doCalculate(String equation) {
// make it explicit:
System.out.println("Got:" + equation);
Pattern pattern = Pattern.compile("([0-9]+|[a-z\\)])(?=[0-9]+|[a-z\\(])");
Matcher m = pattern.matcher(equation);
System.out.println("Made it: "+ (equation = m.replaceAll("$1*")));
//our stacks for storage/temp variables
Stack<Operator> operatorStack;
Stack<Double> operandStack;
double valOne, valTwo, newVal;
Operator temp;
This is an attempt to capture implicit multiplication using regex and make it explicit.
It fixes all cases we've come up with.

Method not working?

Updated code:
import java.util.*;
public class Main {
/**
* #param args
*/
static int[] C;
static int[] D;
static String P;
public static void main(String[] args) {
C = new int[10];
D = new int[10];
getNumber();
}
private static void getNumber() {
System.out
.println("Enter your first number with spaces in between digits.");
Scanner S = new Scanner(System.in);
String O = S.nextLine();
String[] A = new String[10];
A = O.split(" ");
for (int X = 0; A.length > X; X++) {
C[X] = toNumber(A[X]);
}
String P = S.nextLine();
String[] B = new String[10];
B = P.split(" ");
for (int Y = 0; B.length > Y; Y++) {
C[Y] = toNumber(A[Y]);
}
System.out.print(C[0]);
remainders();
}
private static void remainders() {
for (int A = 0; C.length > A; A++) {
if (D[1] * C[A] >= 10) {
Integer B = new Integer(D[1] * C[A]);
Character E = B.toString().charAt(0);
P.concat(E.toString());
}
}
for (int A = 0; C.length > A; A++) {
if (D[0] * C[A] >= 10) {
Integer B = new Integer(D[1] * C[A]);
Character E = B.toString().charAt(0);
P.concat(E.toString());
}
}
System.out.print(P);
}
private static int toNumber(String string) {
if (string.equals("0")) {
return 0;
} else if (string.equals("1")) {
return 1;
} else if (string.equals("2")) {
return 2;
} else if (string.equals("3")) {
return 3;
} else if (string.equals("4")) {
return 4;
} else if (string.equals("5")) {
return 5;
} else if (string.equals("6")) {
return 6;
} else if (string.equals("7")) {
return 7;
} else if (string.equals("8")) {
return 8;
} else if (string.equals("9")) {
return 9;
} else {
return 0;
}
}
}
For some reason, the last thing it prints is null. I am pretty sure the problem is the toNumber method, but I can't figure out what's wrong. If there are other problems with the code other than this, please let me know. Please help.
Edit: Problem seems to be with remainder method, please help
Use the string.equals(n) method to test if string is n
String constants are compared this way: "0".equals(string). String literals are actual String objects and You can call any String method on them. And you should prefer to call methods on constants, because it's guaranteed they exists, whereas variables can be null.
You don't need to reinvent the wheel. Java has rich SDK.
Simply use
int x = Integer.valueOf(a[X]);
If you want only numbers 0-9, then simply test
if (0 <= x && x <= 9) {
//valid continue
} else {
//invalid state handling
}

Categories