I have in a class the following code...
String processor()
{
Stack<Character> stack = new Stack<>();
while (curr < infixExpr.length())
{
// assigning the current index position of string in infix expression to a variable to reduce amount of repeated code
Character element = infixExpr.charAt(curr);
if (isOperand(element))
{
postfixExpr += "" + element;
}
else if (element == '(')
{
stack.push(element);
}
else if (element == ')')
{
while (!stack.peek().equals('('))
{
postfixExpr += stack.pop(); // adding all items in stack after ( and before )
}
stack.pop(); // this should pop the stack of the waiting pushed ( paren and remove it from our postfix expression, basically ignoring it
// right paren found to trigger this else if statement was never pushed onto the stack nor assigned to the postfix expression, also ignored
}
else //*must be an operator then
{
while (OrdOpsTable.getOperatorPrecedence(stack.peek(), true) > OrdOpsTable.getOperatorPrecedence(element, false)) // flag, 'true' to signify this is from the stack. ALso, compare if it has higher precedence over the current operator
{
postfixExpr += stack.pop(); // placing found operator to end of postfix expression
}
stack.push(element);
}
curr++;
}
while (!stack.isEmpty())
{
postfixExpr += stack.pop();
}
return postfixExpr;
}
In the method "getOperatorPrecedence" parameters, I have a Stack instance called stack, calling the method peek, returning a Character Object. As the field element shows, element is of Character Object type. I created a simple flag boolean in the method parameters to make this simple.
So, the "getOperatorPrecedence" is in another class file called "OrdOpsTable"...
public final class OrdOpsTable<T> extends ArrayList
{
// INITIALIZERS
private static Character[] table = {'(','+','-','*','/','%','^'};
private static ArrayList<OperatorValues> ON_stack = new ArrayList<>();
private static ArrayList<OperatorValues> ON_curr = new ArrayList<>();
private T FROM_stack = null;
private T FROM_curr = null;
// CONSTRUCTOR
private OrdOpsTable(T curr)
{
setOperatorPrecedence();
if (curr.getClass() == Stack.class)
this.FROM_stack = curr;
else
this.FROM_curr = curr;
}
// METHODS
private static void setOperatorPrecedence()
{
// this method just sets the unique values of each operator to two arrays
int i = 0;
for (char op : table)
{
switch(op)
{
case '(':
ON_stack.add(i, new OperatorValues(op, 0));
ON_curr.add(i, new OperatorValues(op, 100));
break;
case '+':
ON_stack.add(i, new OperatorValues(op, 2));
ON_curr.add(i, new OperatorValues(op, 1));
break;
case '-':
ON_stack.add(i, new OperatorValues(op, 2));
ON_curr.add(i, new OperatorValues(op, 1));
break;
case '*':
ON_stack.add(i, new OperatorValues(op, 4));
ON_curr.add(i, new OperatorValues(op, 3));
break;
case '/':
ON_stack.add(i, new OperatorValues(op, 4));
ON_curr.add(i, new OperatorValues(op, 3));
break;
case '%':
ON_stack.add(i, new OperatorValues(op, 4));
ON_curr.add(i, new OperatorValues(op, 3));
break;
case '^':
ON_stack.add(i, new OperatorValues(op, 5));
ON_curr.add(i, new OperatorValues(op, 6));
break;
}
i++;
}
}
public static int getOperatorPrecedence(Object curr, boolean FROM_stack)
{
setOperatorPrecedence();
if (FROM_stack)
{
return ON_stack.get(ON_stack.indexOf(curr)).value;
}
else
{
return ON_curr.get(ON_stack.indexOf(curr)).value;
}
}
/* SUBCLASS */
private static class OperatorValues
{
// FIELDS
private char operator;
private int value;
// CONSTRUCTOR
OperatorValues(char operator, int value)
{
this.operator = operator;
this.value = value;
}
// METHOD
char getOperator()
{
return this.operator;
}
int getValue()
{
return this.value;
}
public String toString()
{
return this.operator;
}
}
What I need help with is finding a way to correctly return the OperatorValue subclass field value for both instances of
return ON_stack.get(ON_stack.indexOf(curr)).value;
and
return ON_curr.get(ON_stack.indexOf(curr)).value;
I'm getting the following error...
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at java.util.ArrayList.elementData(ArrayList.java:418)
at java.util.ArrayList.get(ArrayList.java:431)
at OrdOpsTable.getOperatorPrecedence(OrdOpsTable.java:79)
at PostfixParser.processor(PostfixParser.java:57)
at InfixPostfixTester.main(InfixPostfixTester.java:78)
It appears when I debug and follow this, the issue is in "Character" class "equals". First, when I force step into the first return statement in question, it goes to the indexOf() in ArrayList...
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
When the debugger hits the .equals method in here, it goes into the Character class...
public boolean equals(Object obj) {
if (obj instanceof Character) {
return value == ((Character)obj).charValue();
}
return false;
}
The issue here is that the IF statement in this equals method is failing at this comparison. It seems it's comparing obj as my custom made OperatorValues class's toString() and it is obviously not an instanceof a Character class. So, it's failing because it's comparing "(" as a Character. I need it to compare '(' to trigger 'true' in this method.
For an example, I assigned the char '(' with an int of '0' in one array and '100' in another array as you can see above in my OrdOpsTable class in the method setOperatorPrecedence(). When the Character class equals() method is called here without using OperatorValues class's toString(), my debugger says the inline value for curr's '(' in this equal method shows, "obj: OrdOpsTable$OperatorValues#636.
If there was a way to make my toString() method in OperatorValues return a Character instead of String. This of course would cause an error if I did so. Any suggestions on what you would do here?
*NOTE: Let me know if I need to provide more info for you. This is a homework assignment from a class, I've spent alot of time stuck on this part and I've tried relentlessly. I need some outsourcing help to understand what I'm missing.
I figured it out, I changed everything that was of Character class to String class and in my OrdOpsTable class, getOperatorPrecedence() method, to force the comparison from its native class of my custom OperatorValues class to String class, I did this...
return ON_stack.get(ON_stack.toString().indexOf(curr)).getValue();
Thanks everyone who did pitch in for the help, appreciate it.
Related
The task is to implement a generic stack (can not use the libraries from java), make the user input an expression using true and false for booleans b1 and b2, logical operators (and, or, not, iff, implies) recognize if its boolean or operator and send to 2 stacks, then poping the stacks to evaluate if its a valid expression, i.e: input:(b1 and b2) implies b3 is a valid expression but B3 and (b2 or) is not, I have issues with the stack part, since the peek is not returning any element, here is my code so far, note: the charat is because I would be checking that the brackets are balanced as well:
public class MyStack<T> {
class StackOverFlowException extends RuntimeException{}
class EmptyStackException extends RuntimeException{}
private T[] stack;
private int top;
public MyStack(int size) {
this.stack = (T[]) new Object[size];
this.top = 0;
}
public boolean isEmpty() {
return this.top == 0;
}
public boolean isFull() {
return this.top == stack.length;
}
public void push(T x) {
if(top == stack.length) {
throw new StackOverFlowException();
}
else {
this.stack[top] = x;
top++;
}
}
public T pop() {
if(isEmpty()) {
throw new EmptyStackException();
}
else {
T value = this.stack[--top];
return value;
}
}
public T peek() {
return this.stack[top];
}
public static void main(String[] args) {
MyStack<String> tf = new MyStack(100);
MyStack<String> operators = new MyStack(100);
System.out.println("Please input the expression to evaluate: ");
Scanner scn = new Scanner(System.in);
String expression = scn.nextLine();
String tokens[] = expression.split(" ");
int n = tokens.length;
boolean P1 = true;
boolean P2 = true;
boolean result = true;
for(int i = 0; i < n; i++ ) {
String separate = tokens[i];
char x = separate.charAt(i);
if(tokens[i].equalsIgnoreCase("true")||tokens[i].equalsIgnoreCase("false")) {
tf.push(separate);
tf.peek();
}
else if(tokens[i].equalsIgnoreCase("and")||tokens[i].equalsIgnoreCase("not")||tokens[i].equalsIgnoreCase("or")||tokens[i].equalsIgnoreCase("implies")||tokens[i].equalsIgnoreCase("iff")) {
operators.push(separate);
}
else {
System.out.println("Expression not Valid!");
}
}
}
The top variable is being misinterpreted in the peek() method (as well as the isEmpty() method).
As implemented, top is a misnomer since it is actually the size of the stack (which may also be considered the index for the next element to be pushed). So your peek() method should be looking at the element before top.
Alternatively, you may to define top as the element at the top of the stack, as this is generally how you are using it elsewhere. In this case, you will need to define a flag value to indicate the stack is empty.
In any case, you need handle the empty Stack case in the peek() method.
public class MyStack {
private static final int EMPTY = -1;
private int top = EMPTY;
... other stuff ...
public boolean isEmpty() {
return EMPTY == top;
}
public T peek() {
if (ifEmpty()) {
throw new EmptyStackException("Cannot peek into empty Stack");
}
return stack[top];
}
}
so i am making a presentation about parse tree and i do copy paste the code that you will see, but it baffles me that it got an error on the if condition, it says that "the operator && is undefined for the argument type(s) boolean, Operator"(can you tell me why this happen btw i'm kinda new), and i do checked the code and frankly i do not know where it went wrong. as far as i checked all of it return a number which should be fine but i do get the error.
this the code that has the error :
if (OperatorList != null && OperatorList.get(OperatorList.size()))
this is the full code of the main :
public static void main(String[] args) {
ParseTree tree;
String problem = "3+5*16/2^2-6";
ArrayList<Operator> OperatorList = new ArrayList<Operator>();
ArrayList<Node> NodeList = new ArrayList<Node>();
//takes the problem and converts every character into
//an operator and then places them in the operator list
for (int i = 0; i < problem.length(); i++)
{
System.out.println("success.");
switch(problem.charAt(i)) {
case '+':
OperatorList.add(new Plus());
break;
case '-':
OperatorList.add(new Minus());
break;
case '*':
OperatorList.add(new Multiply());
break;
case '/':
OperatorList.add(new Divide());
break;
case '^':
OperatorList.add(new Power());
break;
default:
//checks if the integer has two digits and combines it into one operator
if (OperatorList != null && OperatorList.get(OperatorList.size())) {
int num = OperatorList.remove(i-1).Operate();
num *= 10;
OperatorList.add(new Integer((int) problem.charAt(i) + num));
} else {
OperatorList.add(new Integer((int) problem.charAt(i)));
}
}
}
//places each operator into their own node and
//puts it into a node list
for (int i = 0; i < OperatorList.size(); i++) {
System.out.println(OperatorList.get(i));
NodeList.add(new Node(OperatorList.get(i)));
}
}
}
would you mind telling me why it gives the error? i see nothing returning anything but a number except for the node page which has this code (i am assumming the problem comes from here, but i do not know for sure), here is the code :
public class Node {
private Node left;
private Node right;
private Node parent;
private Operator content;
public Node(Operator op) {
this.content = op;
left = null;
right = null;
parent = null;
}
public Node() {
this(null);
}
public void setLeft(Node n) {
this.left = n;
}
public void setRight(Node n) {
this.right = n;
}
public void setParent(Node n) {
this.parent = n;
}
public void setOperator(Operator op) {
this.content = op;
}
public Node getLeft() {
return this.left;
}
public Node getRight() {
return this.right;
}
public Node getParent() {
return this.parent;
}
public Operator getContent() {
return this.content;
}
public int getOrder() {
return this.content.getOrder();
}
}
am sorry for my english, and thank you for your help
here is the link where i copy the code incase you need it:
https://github.com/McJet/ParseTree
Replace it with
if(OperatorList != null && !OperatorList.isEmpty())
It is pretty basic stuff, try to run through java basics again
The second part of your if-statement doesn't return a boolean. When you use OperatorList.get(OperatorList.size()) it returns an Operator object. If-statements can't evaluate non-boolean values. Remember, if-statements checks if a statement is true. It's like asking if the integer 5 is true or not. The error essentially means, that you are comparing a boolean value to an Operator object, which is not possible. Also list.get(list.size()) will give an exception, as list.size() will always be 1 more than the last index. Instead you should write list.get(list.size()-1)
package edu.bsu.cs121.mamurphy;
import java.util.Stack;
public class Checker {
char openPara = '(';
char openBracket = '[';
char openCurly = '{';
char openArrow = '<';
char closePara = ')';
char closeBracket = ']';
char closeCurly = '}';
char closeArrow = '>';
public boolean checkString(String stringToCheck) {
Stack<Character> stack = new Stack<Character>();
for (int i = 0; i < stringToCheck.length(); i++) {
char c = stringToCheck.charAt(i);
if (c == openPara || c == openBracket || c == openCurly || c == openArrow) {
stack.push(c);
System.out.println(stack);
;
}
if (c == closePara) {
if (stack.isEmpty()) {
System.out.println("Unbalanced");
break;
} else if (stack.peek() == openPara) {
stack.pop();
} else if (stack.size() > 0) {
System.out.println("Unbalanced");
break;
}
}
if (c == closeBracket) {
if (stack.isEmpty()) {
System.out.println("Unbalanced");
break;
} else if (stack.peek() == openBracket) {
stack.pop();
} else if (stack.size() > 0) {
System.out.println("Unbalanced");
break;
}
}
if (c == closeCurly) {
if (stack.isEmpty()) {
System.out.println("Unbalanced");
break;
} else if (stack.peek() == openCurly) {
stack.pop();
} else if (stack.size() > 0) {
System.out.println("Unbalanced");
break;
}
}
if (c == closeArrow) {
if (stack.isEmpty()) {
System.out.println("Unbalanced");
break;
} else if (stack.peek() == openArrow) {
stack.pop();
} else if (stack.size() > 0) {
System.out.println("Unbalanced");
break;
}
}
}
return false;
}
}
I am currently trying to create a program where I check to see if a string is balanced or not. A string is balanced if and only if each opening character: (, {, [, and < have a matching closing character: ), }, ], and > respectively.
What happens is when checking through the string, if an opening character is found, it is pushed into a stack, and it checks to see if there is the appropriate closing character.
If there is a closing character before the opening character, then that automatically means that the string is unbalanced. Also, the string is automatically unbalanced if after going to the next character there is something still inside of the stack.
I tried to use
else if (stack.size() > 0) {
System.out.println("Unbalanced");
break;
}
as a way of seeing if the stack still had anything in it, but it still isn't working for me. Any advice on what to do?
For example, if the string input were ()<>{() then the program should run through like normal until it gets to the single { and then the code should realize that the string is unbalanced and output Unbalanced.
For whatever reason, my code does not do this.
The following logic is flawed (emphasis mine):
For example, if the string input were ()<>{() then the program should run through like normal until it gets to the single { and then the code should realize that the string is unbalanced and output Unbalanced.
In fact, the code can't conclude that the string is unbalanced until it has scanned the entire string and established that the { has no matching }. For all it knows, the full input could be ()<>{()} and be balanced.
To achieve this, you need to add a check that ensures that the stack is empty after the entire string has been processes. In your example, it would still contain the {, indicating that the input is not balanced.
I took a shot at answering this. My solutions returns true if the string is balanced and enforces opening/closing order (ie ({)} returns false). I started with your code and tried to slim it down.
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
public class mamurphy {
private static final char openPara = '(';
private static final char openBracket = '[';
private static final char openCurly = '{';
private static final char openArrow = '<';
private static final char closePara = ')';
private static final char closeBracket = ']';
private static final char closeCurly = '}';
private static final char closeArrow = '>';
public static void main(String... args) {
System.out.println(checkString("{}[]()90<>"));//true
System.out.println(checkString("(((((())))"));//false
System.out.println(checkString("((())))"));//false
System.out.println(checkString(">"));//false
System.out.println(checkString("["));//false
System.out.println(checkString("{[(<>)]}"));//true
System.out.println(checkString("{[(<>)}]"));//false
System.out.println(checkString("( a(b) (c) (d(e(f)g)h) I (j<k>l)m)"));//true
}
public static boolean checkString(String stringToCheck) {
final Map<Character, Character> closeToOpenMap = new HashMap<>();
closeToOpenMap.put(closePara, openPara);
closeToOpenMap.put(closeBracket, openBracket);
closeToOpenMap.put(closeCurly, openCurly);
closeToOpenMap.put(closeArrow, openArrow);
Stack<Character> stack = new Stack<>();
final char[] stringAsChars = stringToCheck.toCharArray();
for (int i = 0; i < stringAsChars.length; i++) {
final char current = stringAsChars[i];
if (closeToOpenMap.values().contains(current)) {
stack.push(current); //found an opening char, push it!
} else if (closeToOpenMap.containsKey(current)) {
if (stack.isEmpty() || closeToOpenMap.get(current) != stack.pop()) {
return false;//found closing char without correct opening char on top of stack
}
}
}
if (!stack.isEmpty()) {
return false;//still have opening chars after consuming whole string
}
return true;
}
}
Here's an alternate approach:
private static final char[] openParens = "[({<".toCharArray();
private static final char[] closeParens = "])}>".toCharArray();
public static boolean isBalanced(String expression){
Deque<Character> stack = new ArrayDeque<>();
for (char c : expression.toCharArray()){
for (int i = 0; i < openParens.length; i++){
if (openParens[i] == c){
// This is an open - put it in the stack
stack.push(c);
break;
}
if (closeParens[i] == c){
// This is a close - check the open is at the top of the stack
if (stack.poll() != openParens[i]){
return false;
}
break;
}
}
}
return stack.isEmpty();
}
It simplifies the logic to have two corresponding arrays of open and close symbols. You could also do this with even and odd positions in one array - ie. "{}<>", for example:
private static final char[] symbols = "[](){}<>".toCharArray();
public static boolean isBalanced(String expression){
Deque<Character> stack = new ArrayDeque<>();
for (char c : expression.toCharArray()){
for (int i = 0; i < symbols.length; i += 2){
if (symbols[i] == c){
// This is an open - put it in the stack
stack.push(c);
break;
}
if (symbols[i + 1] == c){
// This is a close - check the open is at the top of the stack
if (stack.poll() != symbols[i]){
return false;
}
break;
}
}
}
return stack.isEmpty();
}
Note that poll returns null if the stack is empty, so will correctly fail the equality comparison if we run out of stack.
For example, if the string input were ()<>{() then the program should run through like normal until it gets to the single { and then the code should realize that the string is unbalanced and output Unbalanced.
It is not clear by your example whether the boundaries can be nested like ([{}]). If they can, that logic will not work, as the whole string has to be consumed to be sure any missing closing-chars aren't at the end, and so, the string cannot be reliably deemed unbalanced at the point you indicate.
Here is my take on your problem:
BalanceChecker class:
package so_q33378870;
import java.util.Stack;
public class BalanceChecker {
private final char[] opChars = "([{<".toCharArray();
private final char[] edChars = ")]}>".toCharArray();
//<editor-fold defaultstate="collapsed" desc="support functions">
public boolean isOPChar(char c) {
for (char checkChar : opChars) {
if (c == checkChar) {
return true;
}
}
return false;
}
public boolean isEDChar(char c) {
for (char checkChar : edChars) {
if (c == checkChar) {
return true;
}
}
return false;
}
//NOTE: Unused.
// public boolean isBoundaryChar(char c) {
// boolean result;
// if (result = isOPChar(c) == false) {
// return isEDChar(c);
// } else {
// return result;
// }
// }
public char getOpCharFor(char c) {
for (int i = 0; i < edChars.length; i++) {
if (c == edChars[i]) {
return opChars[i];
}
}
throw new IllegalArgumentException("The character (" + c + ") received is not recognized as a closing boundary character.");
}
//</editor-fold>
public boolean isBalanced(char[] charsToCheck) {
Stack<Character> checkStack = new Stack<>();
for (int i = 0; i < charsToCheck.length; i++) {
if (isOPChar(charsToCheck[i])) {
//beginning char found. Add to top of stack.
checkStack.push(charsToCheck[i]);
} else if (isEDChar(charsToCheck[i])) {
if (checkStack.isEmpty()) {
//ending char found without beginning chars on the stack. UNBALANCED.
return false;
} else if (getOpCharFor(charsToCheck[i]) == checkStack.peek()) {
//ending char found matches last beginning char on the stack. Pop and continue.
checkStack.pop();
} else {
//ending char found, but doesn't match last beginning char on the stack. UNBALANCED.
return false;
}
}
}
//the string is balanced if and only if the stack is empty at the end.
return checkStack.empty();
}
public boolean isBalanced(String stringToCheck) {
return isBalanced(stringToCheck.toCharArray());
}
}
Main class (used for testing):
package so_q33378870;
public class main {
private static final String[] tests = {
//Single - Balanced.
"()",
//Single - Unbalanced by missing end.
"(_",
//Multiple - Balanced.
"()[]{}<>",
//Multiple - Unbalanced by missing beginning.
"()[]_}<>",
//Nested - Balanced.
"([{<>}])",
//Nested - Unbalanced by missing end.
"([{<>}_)",
//Endurance test - Balanced.
"the_beginning (abcd) divider (a[bc]d) divider (a[b{c}d]e) divider (a[b{c<d>e}f]g) the_end"
};
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
BalanceChecker checker = new BalanceChecker();
for (String s : tests) {
System.out.println("\"" + s + "\" is " + ((checker.isBalanced(s)) ? "BALANCED!" : "UNBALANCED!"));
}
}
}
I have four classes.
One contains my linkedstack setup
One is infixtopostfix for prioritization and conversion
Parenthesis for matching
Postfix for evaluation
I have setup almost everything here but it is still returning false anyway I put it.
On another note my equals on !stackMatch.pop().equals(c) is not working due to it being a object type with '!' being a problem.
My programs are simple and straight forward:
LinkedStack.java
public class LinkedStack implements StackInterface {
private Node top;
public LinkedStack() {
top = null;
} // end default constructor
public boolean isEmpty() {
return top == null;
} // end isEmpty
public void push(Object newItem) {
Node n = new Node();
n.setData(newItem);
n.setNext(top);
top = n;
} // end push
public Object pop() throws Exception {
if (!isEmpty()) {
Node temp = top;
top = top.getNext();
return temp.getData();
} else {
throw new Exception("StackException on pop: stack empty");
} // end if
} // end pop
public Object peek() throws Exception {
if (!isEmpty()) {
return top.getData();
} else {
throw new Exception("StackException on peek: stack empty");
} // end if
} // end peek
} // end LinkedStack
InfixToPostfix.java
import java.util.*;
public class InfixToPostfix {
Parenthesis p = new Parenthesis();
LinkedStack stack = new LinkedStack();
String token = ""; // each token of the string
String output = ""; // the string holding the postfix expression
Character topOfStackObject = null; // the top object of the stack, converted to a Character Object
char charValueOfTopOfStack = ' '; // the primitive value of the Character object
/**
* Convert an infix expression to postfix. If the expression is invalid, throws an exception.
* #param s the infix expression
* #return the postfix expression as a string
* hint: StringTokenizer is very useful to this iteratively
*/
//public String convertToPostfix(String s) throws Exception {
//}
private boolean isOperand (char c){
return ((c>= '0' && c <= '9') || (c >= 'a' && c<= 'z'));
}
public void precedence(char curOp, int val) throws Exception {
while (!stack.isEmpty()) {
char topOp = (Character) stack.pop();
// charValueOfTopOfStack = topOfStackObject.charValue();
if (topOp == '(') {
stack.push(topOp);
break;
}// it's an operator
else {// precedence of new op
int prec2;
if (topOp == '+' || topOp == '-') {
prec2 = 1;
} else {
prec2 = 2;
}
if (prec2 < val) // if prec of new op less
{ // than prec of old
stack.push(topOp); // save newly-popped op
break;
} else // prec of new not less
{
output = output + topOp; // than prec of old
}
}
}
}
Parenthesis.java
import java.util.*;
public class Parenthesis{
private LinkedStack stack = new LinkedStack();
private Object openBrace;
private String outputString;
/**
* Determine if the expression has matching parenthesis using a stack
*
* #param expr the expression to be evaluated
* #return returns true if the expression has matching parenthesis
*/
public boolean match(String expr) {
LinkedStack stackMatch = new LinkedStack();
for(int i=0; i < expr.length(); i++) {
char c = expr.charAt(i);
if(c == '(')
stackMatch.push(c);
else if(c == ')'){
if (stackMatch.isEmpty() || !stackMatch.pop().equals(c))
return false;
}
}
return stackMatch.isEmpty();
}
}
Just wanted to give you all of it so you could help me. I have tests written already just struggling with the parenthesis problem of pushing it on the stack but unable to compare it to the closing parenthesis so it can check if there is enough while checking to be sure it is not empty.
The problem probably is, that you are trying to test if matching ( is currently on top of the stack when ) comes, but in c is acctual character, ), so you test if ) is on top of stack, not ( as you should.
I am trying to check if a string is a palindrome, but it seems it does not work, because when I send a string that I know is not a palindrome, it returns that it is a palindrome, can anyone help? It also won't add to the variable counter.
package UnaryStack.RubCol1183;
public class CheckPalindrome {
static int counter = 0;
/** Decides whether the parentheses, brackets, and braces
in a string occur in left/right pairs.
#param expression a string to be checked
#return true if the delimiters are paired correctly */
public static boolean checkBalance(String expression)
{
StackInterface<Character> temporaryStack = new LinkedStack<Character>();
StackInterface<Character> reverseStack = new LinkedStack<Character>();
StackInterface<Character> originalStack = new LinkedStack<Character>();
int characterCount = expression.length();
boolean isBalanced = true;
int index = 0;
char nextCharacter = ' ';
for (;(index < characterCount); index++)
{
nextCharacter = expression.charAt(index);
switch (nextCharacter)
{
case '.': case '?': case '!': case '\'': case ' ': case ',':
break;
default:
{
{
reverseStack.push(nextCharacter);
temporaryStack.push(nextCharacter);
originalStack.push(temporaryStack.pop());
}
{
char letter1 = Character.toLowerCase(originalStack.pop());
char letter2 = Character.toLowerCase(reverseStack.pop());
isBalanced = isPaired(letter1, letter2);
if(isBalanced == false){
counter++;
}
}
break;
}
} // end switch
} // end for
return isBalanced;
} // end checkBalance
// Returns true if the given characters, open and close, form a pair
// of parentheses, brackets, or braces.
private static boolean isPaired(char open, char close)
{
return (open == close);
} // end isPaired
public static int counter(){
return counter;
}
}//end class
Your implementation seems way more complex than it needs to be.
//Check for invalid characters first if needed.
StackInterface<Character> stack = new LinkedStack<Character>();
for (char ch: expression.toCharArray()) {
Character curr = new Character(ch);
Character peek = (Character)(stack.peek());
if(!stack.isEmpty() && peek.equals(curr)) {
stack.pop();
} else {
stack.push(curr)
}
}
return stack.isEmpty();
Honestly using a stack is over kill here. I would use the following method.
int i = 0;
int j = expression.length() - 1;
while(j > i) {
if(expression.charAt(i++) != expression.charAt(j--)) return false;
}
return true;
You put exaclty the same elemets in reverseStack and originalStack, because everything you push into the temporaryStack will be immediately pushed into originalStack. This does not make sense.
reverseStack.push(nextCharacter);
temporaryStack.push(nextCharacter);
originalStack.push(temporaryStack.pop());
Therefore the expression
isBalanced = isPaired(letter1, letter2);
will always return true.
I found the errors in logic that were found inside the method checkBalace() and finished the code into a full working one. Here is what my finished code looks like:
public class CheckPalindrome {
static int counter;
/** Decides whether the parentheses, brackets, and braces
in a string occur in left/right pairs.
#param expression a string to be checked
#return true if the delimiters are paired correctly */
public static boolean checkBalance(String expression)
{
counter = 0;
StackInterface<Character> temporaryStack = new LinkedStack<Character>();
StackInterface<Character> reverseStack = new LinkedStack<Character>();
StackInterface<Character> originalStack = new LinkedStack<Character>();
boolean isBalanced = true;
int characterCount = expression.length();
int index = 0;
char nextCharacter = ' ';
for (;(index < characterCount); index++)
{
nextCharacter = expression.charAt(index);
switch (nextCharacter)
{
case '.': case '?': case '!': case '\'': case ' ': case ',':
break;
default:
{
{
reverseStack.push(nextCharacter);
temporaryStack.push(nextCharacter);
}
break;
}
} // end switch
} // end for
while(!temporaryStack.isEmpty()){
originalStack.push(temporaryStack.pop());
}
while(!originalStack.isEmpty()){
char letter1 = Character.toLowerCase(originalStack.pop());
char letter2 = Character.toLowerCase(reverseStack.pop());
isBalanced = isPaired(letter1, letter2);
if(isBalanced == false){
counter++;
}
}
return isBalanced;
} // end checkBalance
// Returns true if the given characters, open and close, form a pair
// of parentheses, brackets, or braces.
private static boolean isPaired(char open, char close)
{
return (open == close);
} // end isPaired
public static int counter(){
return counter;
}
}
I used 2 while methods outside of the for thus fixing the logic errors pointed out. I also assigned the value 0 to counter inside the method to fix a small problem I encountered. Feel free to revise the code if I still have errors, but I think I made no errors, then again, I'm a beginner.