In this assignment, I need to read a .txt file and determine if the expressions are correct or "Balanced". The first problem I got correct but for the second problem I am getting more output than I want. Here is the problem for #2:
Write a stack-based algorithm that evaluates a post-fixed expression. Your program needs to read its input from a file called “problem2.txt”. This file contains one expression per line.
For each expression output its value to the standard output. If an expression is ill-formed print “Ill-formed”.
The Problem2.txt is as follows:
3 2 + 5 6 8 2 / + + * 1 +
8 * 2 3 + + - 9 1 +
1 4 + 9 4 - * 2 *
// For my output I need to get:
76
Ill-formed
50
// With my code I am getting:
76
Ill-formatted
Ill-formatted
Ill-formatted
10
50
// and I’m not sure why I’m getting extra ill-formatted and a 10 in there
Below is my code:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Stack;
import java.util.EmptyStackException;
public class Eval {
public static void main(String args[]) throws IOException {
//driver
try (BufferedReader filereader = new BufferedReader(new FileReader("Problem1.txt"))) {
while (true) {
String line = filereader.readLine();
if (line == null) {
break;
}
System.out.println(balancedP(line));
}
}
System.out.println("\n");
try (BufferedReader filereader2 = new BufferedReader(new FileReader("Problem2.txt"))) {
while (true) {
String line = filereader2.readLine();
if (line == null) {
break;
}
System.out.println(evaluatePostfix(line));
}
}
}
public static boolean balancedP (String s) {
Stack<Character> stackEval = new Stack<Character>();
for(int i = 0; i < s.length(); i++) {
char token = s.charAt(i);
if(token == '[' || token == '(' || token == '{' ) {
stackEval.push(token);
} else if(token == ']') {
if(stackEval.isEmpty() || stackEval.pop() != '[') {
return false;
}
} else if(token == ')') {
if(stackEval.isEmpty() || stackEval.pop() != '(') {
return false;
}
} else if(token == '}') {
if(stackEval.isEmpty() || stackEval.pop() != '{') {
return false;
}
}
}
return stackEval.isEmpty();
}
//problem 2 algo to evaluate a post-fixed expression
static int evaluatePostfix(String exp) throws EmptyStackException
{
Stack<Integer> stackEval2 = new Stack<>();
for(int i = 0; i < exp.length(); i++)
{
char c = exp.charAt(i);
if(c == ' ')
continue;
else if(Character.isDigit(c)) {
int n = 0;
while(Character.isDigit(c)) {
n = n*10 + (int)(c-'0');
i++;
c = exp.charAt(i);
}
i--;
stackEval2.push(n);
}
else {
try {
//if operand pops two values to do the calculation through the switch statement
int val1 = stackEval2.pop();
int val2 = stackEval2.pop();
//operands in a switch to test and do the operator's function each value grabbed and tested
switch(c) {
case '+':
stackEval2.push(val2 + val1);
break;
case '-':
stackEval2.push(val2 - val1);
break;
case '/':
stackEval2.push(val2 / val1);
break;
case '*':
stackEval2.push(val2 * val1);
break;
}
} catch (EmptyStackException e) {
System.out.println("Ill-formatted");
}
}
}
return stackEval2.pop();
}
}
A simple way to have the output formatted how you want is to just put the try-catch block around where you are calling the evaluatePostfix() method (make sure to delete the try-catch block that is inside the evaluatePostfix() method):
System.out.println("\n");
try (BufferedReader filereader2 = new BufferedReader(new FileReader("Problem2.txt"))) {
while (true) {
String line = filereader2.readLine();
if (line == null) {
break;
}
try {
System.out.println(evaluatePostfix(line));
} catch (EmptyStackException e) {
System.out.println("Ill-formatted");
}
}
}
This way, when an exception occurs inside the evaluatePostfix() method, the method will throw the exception and the exception will be dealt with outside of the looping, thus, avoiding duplicate error messages and other unwanted effects.
I am writing a program where I should check if the opening parenthesis matches the closing one. If it doesn't match, I should display No. Otherwise, I should display yes.
This is the function I wrote, taking the input from the input buffer. However, I just keep on receiving yes for the second test case, instead of YES NO YES but the other two cases are correct.
static String[] braces(String[] values) {
Stack<Character> st = new Stack<Character>();
String[] answer = new String[values.length];
for(int i =0; i<values.length;i++){
char[] crt = values[i].toCharArray();
for(char c : crt){
switch(c){
case '{':
case '(':
case '[':
st.push(c);
break;
case '}':
if(st.isEmpty() || (st.peek() != '{'))
{
answer[i]= "NO";
break;
}
st.pop();
case ')':
if(st.isEmpty() || (st.peek() != '('))
{
answer[i]= "NO";
break;
}
st.pop();
case ']':
if(st.isEmpty() || (st.peek() != '['))
{
answer[i]= "NO";
break;
}
st.pop();
}
}
if(st.isEmpty() && answer[i].equals("NO") ){
answer[i]="YES";
System.out.println("I set answer[" + i + "] = YES due to stack being empty");
}
else
{
answer[i]="NO";
System.out.println("I set answer[" + i + "] = NO due to stack being non-empty");
}
st.clear();
}
return answer;
}
Change stack.firstElement() to stack.peek(), you need the stack top instead of the first element. (firstElement is not a Stack method)
The great secret of StackOverflow is that it's not actually full of gurus who look at your code the way Neo looks at The Matrix. It's just people examining how your programs runs.
You can do this yourself, and the most ancient and trivial way is through so-called "print debugging".
In short, you just add print statements that prints what your code is doing, and then you follow along and compare it to what you think it should be doing. Here's your code with such print statements added:
import java.util.*;
public class Test {
static String[] braces(String[] values) {
Stack<Character> st = new Stack<Character>();
String[] answer = new String[values.length];
for(int i =0; i<values.length;i++){
char[] crt = values[i].toCharArray();
boolean an = false;
for(char c : crt){
switch(c){
case '{':
case '(':
case '[':
st.push(c);
break;
case '}':
if(st.isEmpty() || (st.firstElement() != '{'))
{
answer[i]= "NO";
System.out.println("I set answer[" + i + "] = NO due to mismatched }");
}
st.pop();
break;
case ')':
if(st.isEmpty() || (st.firstElement() != '('))
{
answer[i]= "NO";
System.out.println("I set answer[" + i + "] = NO due to mismatched )");
}
st.pop();
break;
case ']':
if(st.isEmpty() || (st.firstElement() != '['))
{
answer[i]= "NO";
System.out.println("I set answer[" + i + "] = NO due to mismatched ]");
}
st.pop();
break;
}
}
if(st.isEmpty()){
answer[i]="yes";
System.out.println("I set answer[" + i + "] = YES due to stack being empty");
}
else
{
answer[i]="no";
System.out.println("I set answer[" + i + "] = NO due to stack being non-empty");
}
st.clear();
}
return answer;
}
public static void main(String[] args) {
String[] result = braces(new String[] { "(foo}" });
for(String s : result) System.out.println("The final result is " + s);
}
}
And here's the output, running on the string (foo}:
I set answer[0] = NO due to mismatched }
I set answer[0] = YES due to stack being empty
The final result is yes
Welp, it looks like you're overwriting your previous answer. You should make sure the final test doesn't override the loop's conclusion.
The trivial hack would be to check if answer[i] is null, but the better way would be to create a second helper method boolean braces(String) that is free to return true or false at any time, and then simply call that function in a loop in your braces(String[])
In any case, this would have been my implementation:
import java.util.Stack;
class Test {
static char flip(char c) {
switch(c) {
case '}': return '{';
case ')': return '(';
case ']': return '[';
default: throw new IllegalArgumentException("Invalid paren " + c);
}
}
static boolean matched(String value) {
Stack<Character> st = new Stack<Character>();
for (int i=0; i<value.length(); i++) {
char c = value.charAt(i);
switch(c) {
case '{':
case '(':
case '[':
st.push(c);
break;
case '}':
case ')':
case ']':
if (st.isEmpty() || st.peek() != flip(c)) {
return false;
}
st.pop();
break;
}
}
return st.isEmpty();
}
static String[] braces(String[] values) {
String[] result = new String[values.length];
for(int i=0; i<result.length; i++) {
result[i] = matched(values[i]) ? "yes" : "no";
}
return result;
}
public static void main(String[] args) {
String[] input = new String[] { "}", "{}", "{()}", "asdf", "", "{[", "{[[([])]]}", "((foo))" };
String[] actual = braces(input);
String[] expected = new String[] { "no", "yes", "yes", "yes", "yes", "no", "yes", "yes" };
for(int i=0; i<actual.length; i++) {
if(!actual[i].equals(expected[i])) {
System.out.println("Failed: " + input[i] + " should have been " + expected[i]);
System.exit(1);
}
}
System.out.println("OK");
}
}
import java.util.*;
import java.util.stream.Collectors;
public class Test {
static final Map<Character, Character> PARENS;
static final Set<Character> CLOSING_PARENS;
static {
PARENS = new HashMap<>();
PARENS.put('{', '}');
PARENS.put('[', ']');
PARENS.put('(', ')');
CLOSING_PARENS = new HashSet<>(PARENS.values());
}
public static void main(String[] args) {
print(braces("(foo}","[]","()","{}","[{}]","([{}])","[[]]"));
print(braces("[","]","][","[{]}"));
// test case 2 ...
print(braces("{[()]}","{[(])}","{{[[(())]]}}"));
// ... prints YES NO YES ...
}
static void print(String ... values){
for(String str : values){
System.out.print(str + " ");
}
System.out.println();
}
static String [] braces(String ... values) {
return Arrays.stream(values)
.map(Test::isBalanced)
.map(b -> b ? "YES" : "NO")
.collect(Collectors.toList()).toArray(new String[values.length]);
}
static boolean isBalanced(String token){
Stack<Character> stack = new Stack<>();
for(char c : token.toCharArray()){
if (PARENS.keySet().contains(c)){
stack.push(c);
} else if(CLOSING_PARENS.contains(c)){
if(stack.isEmpty() || !PARENS.get(stack.pop()).equals(c)) {
return false;
}
}
}
return stack.isEmpty();
}
}
you just have to make the following changes
Replace firstElement() with peek() in all cases
remove the following statement from the first two cases
stack.pop();
break;
check if stack is empity at the last case
if(!stack.isEmpty())
corrected code:
public class ParenMatch{
public static void main(String[] args){
String[] str = { "{}[](){[}]","{[()]}{[(])}{{[[(())]]}}","", "}][}}(}][))][](){()}()({}([][]))[](){)[](}]}]}))}(())(([[)"};
System.out.println(Arrays.toString(braces(str)));
}
public static String[] braces(String[] values)
{
Stack<Character> stack = new Stack<Character>();
String[] isCorrect = new String[values.length];
for (int i = 0; i < values.length; i++)
{
char[] crt = values[i].toCharArray();
boolean an = false;
for (char c : crt)
{
switch(c)
{
case '{':
case '(':
case '[':
stack.push(c);
break;
case '}':
if (stack.isEmpty() || (stack.peek() != '{'))
{
isCorrect[i] = "NO";
}
//stack.pop();
//break;
case ')':
if (stack.isEmpty() || (stack.peek() != '('))
{
isCorrect[i] = "NO";
}
//stack.pop();
//break;
case ']':
if (stack.isEmpty() || (stack.peek() != '['))
{
isCorrect[i] = "NO";
}
if(!stack.isEmpty())
stack.pop();
break;
}
}
if (stack.isEmpty())
{
isCorrect[i] = "yes";
}
else
{
isCorrect[i] = "no";
}
stack.clear();
}
return isCorrect;
}
}
input:
String[] str = { "{}[](){[}]","{[()]}{[(])}{{[[(())]]}}","", "}][}}(}][))][](){()}()({}([][]))[](){)[](}]}]}))}(())(([[)"};
output:
[yes, yes, yes, no]
static String[] braces(String[] values) {
Stack<Character> st = new Stack<Character>();
String []answer = new String[values.length];
Boolean isCorrect = false;
for(int i =0; i< values.length;i++)
{
isCorrect = true;
st.clear();
char crt[] = values[i].toCharArray();
for(char c : crt)
{
switch(c)
{
case'{':
case'[':
case'(':
st.push(c);
break;
case'}':
if(st.isEmpty() || st.peek() != '{')
{
System.out.println("Hellooo");
answer[i] ="NO";
isCorrect = false;
}
if(!st.isEmpty())
{
st.pop();
}
break;
case']':
if(st.isEmpty() || st.peek() != '[')
{
System.out.println("Hell");
answer[i] ="NO";
isCorrect = false;
}
if(!st.isEmpty())
{
st.pop();
}
break;
case')':
if(st.isEmpty() || st.peek() != '(')
{
isCorrect = false;
}
if(!st.isEmpty()) {
st.pop();
}
break;
}
}
if(isCorrect && st.isEmpty())
{
answer[i] = "YES";
System.out.println("Hello");
}else answer[i] = "NO";
}
return answer;
}
The code takes in an infix operation and converts it to a postfix operation. I have been able to to the conversion. The problem I'm facing is the spacing between operators. Also, I'd like to know how the postfix operation can be evaluated.
import java.io.IOException;
public class InToPost {
private Stack theStack;
private String input;
private String output = "";
public InToPost(String in) {
input = in;
int stackSize = input.length();
theStack = new Stack(stackSize);
}
public String doTrans() {
for (int j = 0; j < input.length(); j++) {
char ch = input.charAt(j);
switch (ch) {
case '+':
case '-':
gotOper(ch, 1);
break;
case '*':
case '/':
case '%':
gotOper(ch, 2);
break;
case '(':
theStack.push(ch);
break;
case ')':
gotParen(ch);
break;
default:
output = output + ch;
break;
}
}
while (!theStack.isEmpty()) {
output = output + theStack.pop();
}
System.out.println(output);
return output;
}
public void gotOper(char opThis, int prec1) {
while (!theStack.isEmpty()) {
char opTop = theStack.pop();
if (opTop == '(') {
theStack.push(opTop);
break;
}
else {
int prec2;
if (opTop == '+' || opTop == '-')
prec2 = 1;
else
prec2 = 2;
if (prec2 < prec1) {
theStack.push(opTop);
break;
}
else
output = output + opTop;
}
}
theStack.push(opThis);
}
public void gotParen(char ch){
while (!theStack.isEmpty()) {
char chx = theStack.pop();
if (chx == '(')
break;
else
output = output + chx;
}
}
public static void main(String[] args)
throws IOException {
String input = "13 + 23 - 42 * 2";
String output;
InToPost theTrans = new InToPost(input);
output = theTrans.doTrans();
System.out.println("Postfix is " + output + '\n');
}
class Stack {
private int maxSize;
private char[] stackArray;
private int top;
public Stack(int max) {
maxSize = max;
stackArray = new char[maxSize];
top = -1;
}
public void push(char j) {
stackArray[++top] = j;
}
public char pop() {
return stackArray[top--];
}
public char peek() {
return stackArray[top];
}
public boolean isEmpty() {
return (top == -1);
}
}
}
The postfix output for this is:
13 23 + 42 2*-
whereas I am trying to get an output that looks like this:
13 23 + 42 2 * -
I am unable to space the operator in the output.
This question already has answers here:
Handling parenthesis while converting infix expressions to postfix expressions
(2 answers)
Closed 6 years ago.
I tried making my infix to postfix code, it works without the braces, but when I try to include the portion to account for braces, it crashes, here is the main part of the code:
for (i=0; i<characters.length; i++)
{
if (characters[i]=='*' || characters[i]=='/' || characters[i]=='+' || characters[i]=='-' || characters[i]=='(' || characters[i]==')'){
if (postfix.empty() && characters[i]!=')')
postfix.push(characters[i]);
else if (!postfix.empty()){
if (characters[i]=='(')
postfix.push(characters[i]);
if (characters[i]=='*' || characters[i]=='/')
priority2=1;
if (characters[i]=='+' || characters[i]=='-')
priority2=0;
if (characters[i]==')'){
while (postfix.peek()!='(') //loop until we see the closing bracket
System.out.print(postfix.pop()); //pop everything till we see the closing bracket
postfix.pop(); //to pop the bracket
}
if (!postfix.empty())
peeked=postfix.peek();
if (peeked=='*' || peeked=='/')
priority=1;
if (peeked=='+' || peeked=='-')
priority=0;
if (priority2>priority)
postfix.push(characters[i]);
else{
while (!postfix.empty())
System.out.print(postfix.pop());
postfix.push(characters[i]);
}
}
}
else
System.out.print(characters[i]);
}
while (!postfix.empty())
System.out.print(postfix.pop());
Any help would be appreciated. It breaks when it comes to a brace.
You can get some insight from my implementation of Infix To Postfix program, which is based on the standard algorithm for doing such conversions. Here it is:
import java.util.Scanner;
import java.util.Stack;
public class InfixPostfix
{
private Stack<Character> stack;
private StringBuilder postfixExpression;
public InfixPostfix()
{
stack = new Stack<>();
postfixExpression = new StringBuilder();
String infix = getInfixExpression();
if (isValidInfix(infix))
{
System.out.println(convertToPostfix(infix));
}
else
{
System.out.println("Invalid Expression");
}
}
private boolean isValidInfix(String infix)
{
int parenthesisCounter = 0;
for (int i = 0; i < infix.length(); i++)
{
char ch = infix.charAt(i);
if (ch == '(')
parenthesisCounter++;
else if (ch == ')')
parenthesisCounter--;
if (parenthesisCounter < 0)
return false;
}
if (parenthesisCounter == 0)
return true;
return false;
}
private String convertToPostfix(String infix)
{
for (int i = 0; i < infix.length(); i++)
{
char ch = infix.charAt(i);
switch (ch)
{
case '+':
case '-':
processOperatorOfPrecedence(ch, 1);
break;
case '*':
case '/':
processOperatorOfPrecedence(ch, 2);
break;
case '(':
stack.push(ch);
break;
case ')':
processParenthesis(ch);
break;
default:
postfixExpression.append(ch);
break;
}
}
while (!stack.isEmpty())
{
postfixExpression.append(stack.pop());
}
return postfixExpression.toString();
}
private void processOperatorOfPrecedence(char operator, int precedence)
{
while (!stack.isEmpty())
{
char topOperator = stack.pop();
if (topOperator == '(')
{
stack.push(topOperator);
break;
}
else
{
int operatorPrecedence;
if (topOperator == '+' || topOperator == '-')
operatorPrecedence = 1;
else
operatorPrecedence = 2;
if (operatorPrecedence < precedence)
{
stack.push(topOperator);
break;
}
else
postfixExpression.append(topOperator);
}
}
stack.push(operator);
}
private void processParenthesis(char ch)
{
while (!stack.isEmpty())
{
char character = stack.pop();
if (character == '(')
break;
else
postfixExpression.append(character);
}
}
private String getInfixExpression()
{
Scanner scanner = new Scanner(System.in);
System.out.println("Enter an infix math expression: ");
String input = scanner.nextLine();
scanner.close();
return input;
}
public static void main(String[] args)
{
new InfixPostfix();
}
}
I've created a stack calculator for my Java class to solve equations such as
2 + ( 2 * ( 10 – 4 ) / ( ( 4 * 2 / ( 3 + 4) ) + 2 ) – 9 )
2 + { 2 * ( 10 – 4 ) / [ { 4 * 2 / ( 3 + 4) } + 2 ] – 9 }
We are suppose to implement { } [ ] into our code. I did it with just parentheses. It works 100% with just ( ). When I try to add { } [ ], it goes bananas.
This is what I have so far:
package stackscalc;
import java.util.Scanner;
import java.util.Stack;
import java.util.EmptyStackException;
class Arithmetic {
int length;
Stack stk;
String exp, postfix;
Arithmetic(String s) {
stk = new Stack();
exp = s;
postfix = "";
length = exp.length();
}
boolean isBalance() {
boolean fail = false;
int index = 0;
try {
while (index < length) {
char ch = exp.charAt(index);
switch(ch) {
case ')':
stk.pop();
break;
case '(':
stk.push(new Character(ch));
break;
default:
break;
}
index++;
}
} catch (EmptyStackException e) {
fail = true;
}
return stk.empty() && !fail;
}
void postfixExpression() {
String token = "";
Scanner scan = new Scanner(exp);
stk.clear();
while(scan.hasNext()) {
token = scan.next();
char current = token.charAt(0);
if (isNumber(token)) {
postfix = postfix + token + " ";
} else if(isParentheses(current)) {
if (current == '(') {
stk.push(current);
} else {
Character ch = (Character) stk.peek();
char nextToken = ch.charValue();
while(nextToken != '(') {
postfix = postfix + stk.pop() + " ";
ch = (Character) stk.peek();
nextToken = ch.charValue();
}
stk.pop();
}
} else {
if (stk.empty()) {
stk.push(current);
} else {
Character ch = (Character) stk.peek();
char top = ch.charValue();
if (hasHigherPrecedence(top, current)) {
stk.push(current);
} else {
ch = (Character) stk.pop();
top = ch.charValue();
stk.push(current);
stk.push(top);
}
}
}
}
try {
Character ch = (Character) stk.peek();
char nextToken = ch.charValue();
while (isOperator(nextToken)) {
postfix = postfix + stk.pop() + " ";
ch = (Character) stk.peek();
nextToken = ch.charValue();
}
} catch (EmptyStackException e) {}
}
boolean isNumber(String s) {
try {
int Num = Integer.parseInt(s);
} catch(NumberFormatException e) {
return false;
}
return true;
}
void evaluateRPN() {
Scanner scan = new Scanner(postfix);
String token = "";
stk.clear();
while(scan.hasNext()) {
try {
token = scan.next();
if (isNumber(token)) {
stk.push(token);
} else {
char current = token.charAt(0);
double t1 = Double.parseDouble(stk.pop().toString());
double t2 = Double.parseDouble(stk.pop().toString());
double t3 = 0;
switch (current) {
case '+': {
t3 = t2 + t1;
stk.push(t3);
break;
}
case '-': {
t3 = t2 - t1;
stk.push(t3);
break;
}
case '*': {
t3 = t2 * t1;
stk.push(t3);
break;
}
case '/': {
t3 = t2 / t1;
stk.push(t3);
break;
}
default: {
System.out.println("Reverse Polish Notation was unable to be preformed.");
}
}
}
} catch (EmptyStackException e) {}
}
}
String getResult() {
return stk.toString();
}
int stackSize() {
return stk.size();
}
boolean isParentheses(char current) {
if ((current == '(') || (current == ')')) {
return true;
} else {
return false;
}
}
boolean isOperator(char ch) {
if ((ch == '-')) {
return true;
} else if ((ch == '+')) {
return true;
}
else if ((ch == '*')) {
return true;
}
else if((ch == '/')) {
return true;
} else {
}
return false;
}
boolean hasHigherPrecedence(char top, char current) {
boolean HigherPre = false;
switch (current) {
case '*':
HigherPre = true;
break;
case '/':
HigherPre = true;
break;
case '+':
if ((top == '*') || (top == '/') || (top == '-')) {
HigherPre = false;
} else {
HigherPre = true;
}
break;
case '-':
if ((top == '*') || (top == '/') || (top == '-')) {
HigherPre = false;
} else {
HigherPre = true;
}
break;
default:
System.out.println("Higher Precedence Unsuccessful was unable to be preformed.");
break;
}
return HigherPre;
}
String getPostfix() {
return postfix;
}
}
What I am assuming is that (), {}, and [] all have the same weight in terms of order of operations, and you just need to modify your code in order to allow for all three interchangeably.
If that is the case, I would just use the matcher class with a simple regex check to see if the current char that you are looking at is either a parenthesis, curly brace, or bracket.
//convert char to string
String temp += currentChar;
//this will check for (, [, and { (need escapes because of how regex works in java)
Pattern bracePattern = Pattern.compile("[\(\{\[]");
Matcher matcher = numPatt.matcher(temp);
if(matcher.find()){
//you know you have a grouping character
}
This code should allow you to find all the opening grouping characters (just substitute (,{, and [ for ),} and ] in the regex to find closing characters). This can be used in your isParenthesis() method.
You could use a method like this to streamline checking if a '(', '[', or '{' is matched or not.
static char getExpected(char val){
char expected=' ';
switch (val) {
case '(':
expected=')';
break;
case '[':
expected=']';
break;
case '{':
expected='}';
break;
}
return expected;
}