the code checks if delimiters are balanced in the string or not. I've been using a stack to solve this. I traverse the string to the end, whenever an opening delimiter is encountered I push it into the stack, for each closing delimiter encountered I make a check if the stack is empty (and report error if it is) and then pop the stack to match the popped character and the closing delimiter encountered. I ignore all other characters in the string.
At the end of the traversal I make a check if the stack is empty (that is I check if all the opening delimiters were balanced out or not). If it's not empty, I report an error.
Although I have cross checked many times the code seems to be reporting every string as invaalid(i.e with unbalanced delimiters). Here's the code:
import java.util.*;
public class delimiter {
public static void main(String args[]){
String s1 = "()";
String s2 = "[}[]";
if(delimitercheck(s1)){
System.out.println("s1 is a nice text!");
}
else
System.out.println("S1 is not nice");
if(delimitercheck(s2)){
System.out.println("s2 is a nice text!");
}
else
System.out.println("S2 is not nice");
}
public static boolean delimitercheck(String s){
Stack<Character> stk = new Stack<Character>();
if(s==null||s.length()==0)//if it's a null string return true
return true;
for(int i=0;i<s.length();i++){
if(s.charAt(i)=='('||s.charAt(i)=='{'||s.charAt(i)=='['){
stk.push(s.charAt(i));
}
if(s.charAt(i)==')'||s.charAt(i)=='}'||s.charAt(i)==']'){
if(stk.isEmpty()){
return false;
}
if(stk.peek()==s.charAt(i)){
stk.pop();
}
}
}
if(stk.isEmpty()){
return true;
}
else
return false;
}
}
Can anyone point to me where am I going wrong?
Your error is here :
if(stk.peek()==s.charAt(i)){
stk.pop();
}
The i'th character shouldn't be equal to stk.peek(). It should be closing it. i.e. if stk.peek() == '{', s.charAt(i) should be '}', and so on.
In addition, if the current closing parenthesis doesn't match to top of the stack, you should return false.
You can either have a separate condition for each type of paretheses, or you can create a Map<Character,Character> that maps each opening parenthesis to its corresponding closing parenthesis, and then your condition will become :
if(map.get(stk.peek())==s.charAt(i)){
stk.pop();
} else {
return false;
}
where map can be initialized to :
Map<Character,Character> map = new HashMap<>();
map.put('(',')');
map.put('{','}');
map.put('[',']');
Yes, when encountering a closing bracket, you check if it is similar to the opening bracket which is not correct.
if(stk.peek()==s.charAt(i)){
stk.pop();
}
should be replaced with something similar to
Character toCheck = s.charAt(i);
Character peek = stk.peek();
if (toCheck == ')') {
if (peek == '(') {
stk.pop();
} else {
return false;
}
} else if ( // ... check all three bracket types
And please stick to brackets for every if-statement - there's nothing more tedious then one day encountering an error due to omitted brackets which will cause you more internal pain.
You are checking the stack value which has an opening delimiter with a closing delimiter. So for the first example you are checking '(' with ')'. Instead for every corresponding end delimiter you should check the stack for its starting delimiter i.e., '(' with ')'. Hope that makes sense.
Related
I am working on a program that converts a prefix to a postfix expression. However, when there is an unexpected blank space in an expression such as "$+-ABC+D-E F" instead of "$+-ABC+D-EF" the program doesn't work correctly. How do I write skip to the next character and ignore the whitespace, trying to do it through an if else statement using a boolean isBlank method.
public class PrefixConverter{
// Checks if character is an operator
public boolean isOperator(char c){
switch (c){
case '+':
case '-':
case'*':
case'/':
case'$':
return true;
}
return false;
}
// Ignores white space
public boolean isBlank(char c){
switch (c){
case ' ':
return true;
}
return false;
}
// Method to convert Prefix expression to Postfix expression
public String preToPost (String prefix_exp){
// Create a new stack with length of the prefix string
int size = prefix_exp.length();
Stack expression_stack = new Stack (size);
// Read expression from right to left
for (int i = size -1; i >=0 ; i-- ){
if (isOperator(prefix_exp.charAt(i))){
// Pop two operands from the stack
String op1 = expression_stack.peek();
expression_stack.pop();
String op2 = expression_stack.peek();
expression_stack.pop();
// Concatenate the operands and the operator
String temp = op1 + op2 + prefix_exp.charAt(i);
// Push the result back onto the stack
expression_stack.push(temp);
}
else if(isBlank(prefix_exp.charAt(i))){
// Skip to next character
}
// If the symbol is an operand
else {
// Push the operand onto the stack
expression_stack.push(prefix_exp.charAt(i) + "");
}
}
return expression_stack.peek();
}
}
One way would be to write a continue; in this else if():
else if(isBlank(prefix_exp.charAt(i))){
// Skip to next character
continue;
}
continue will simply move to the next iteration of the loop
However, if you do not need the spaces you can remove them from the prefix_exp String in the beginning by doing this:
prefix_exp = prefix_exp.replaceAll("\\s", "");
Just make sure you do the replaceAll before you call .length() of the String as the size changes.
Just use the continue statement to skip to the end of your for loop.
This will trigger the loop to run with the next character. But since the rest of your code is in if statements anyway, your code should behave well by just doing nothing.
...
else if(isBlank(prefix_exp.charAt(i))){
// Skip to next character
continue;
}
See also https://docs.oracle.com/javase/tutorial/java/nutsandbolts/branch.html
I was doing hackerrank and I am trying to understand the solution written by RodneyShag. (Credit: He wrote the solution, not me) I am trying to understand the last part.
import java.util.Scanner;
import java.util.HashMap;
import java.util.ArrayDeque;
class Solution {
public static void main(String[] args) {
/* Create HashMap to match opening brackets with closing brackets */
HashMap<Character, Character> map = new HashMap<>();
map.put('(', ')');
map.put('[', ']');
map.put('{', '}');
/* Test each expression for validity */
Scanner scan = new Scanner(System.in);
while (scan.hasNext()) {
String expression = scan.next();
System.out.println(isBalanced(expression, map) ? "true" : "false" );
}
scan.close();
}
private static boolean isBalanced(String expression, HashMap<Character, Character> map) {
if ((expression.length() % 2) != 0) {
return false; // odd length Strings are not balanced
}
ArrayDeque<Character> deque = new ArrayDeque<>(); // use deque as a stack
for (int i = 0; i < expression.length(); i++) {
Character ch = expression.charAt(i);
if (map.containsKey(ch)) {
deque.push(ch);
} else if (deque.isEmpty() || ch != map.get(deque.pop())) {
return false;
}
}
return deque.isEmpty();
}
}
The explanation (provided by him) is
Our map only has 3 keys: (, [, { The linemap.containsKey(ch) checks if it's one of the above keys, and if so, pushes it to the deque. The next part of
deque.isEmpty() || ch != map.get(deque.pop())
checks if we have a valid expression. Since at this point, we know the character is not (, [, or {, so we must have a valid closing brace. if
1) our deque is empty, and we just read a closing brace, then we have an invalid expression (and return false)
2) if the closing brace does not match the opening brace that we popped off the deque, then we have an invalid expression (and return false)
I understand that
Character ch = expression.charAt(i);
is supposed to : check whether each variable at expression is = to variable in map Character.
Why is it only ([{ in map? Isn't there ( ) [ ] { } in map?
The map is use to specify which character is the closing bracket given an opening bracket. So when you write
map.get('(')
you get the character ) as defined with
map.put('(', ')');
at the initialization.
What the ch != map.get(deque.pop()) line is checking is if the character ch is an expected closing bracket based on the top value of the stack. To make it more clear/verbose the else if() part can be rewritten as this:
if (map.containsKey(ch)) {
deque.push(ch);
} else {
// 'ch' must be one of ), ] or } (or something completely different) at this point
if (deque.isEmpty()) {
// stack is empty, but shouldn't, so return false
return false;
}
Character lastOpeningBracket = deque.pop(); // is one of (, [ or {
Character expectedClosingBracket = map.get(lastOpeningBracket); // is one of ), ] or }
Character actualReadCharacter = ch; // only for verbosity
if (!expectedClosingBracket.equals(actualReadCharacter)) {
System.out.println("The character "+actualReadCharacter+" was read from\n"+
"the string, but it should be\n"+
"a "+expectedClosingBracket+" character\n"+
"because the last opening bracket was\n"+
"a "+lastOpeningBracket); // only for verbosity
return false;
}
}
(be careful for comparing char and Character, see #matt's comment and What is the difference between == and equals() in Java?. Also check the Character cache which might be used here)
I have a string like:
If ({{SQL}}.Employee.Title starts with 'Production')
and (substring of {{SQL}}.Employee.Title from '27' for '2' is not '30')
and ({{SQL}}.Employee.HireDate is greater than or equal to '2000-01-01 00:00:00.000')
then Pull {{SQL}}.Title, {{SQL}}.HireDate from Employee
From this expression, I want to find out whether round brackets are properly balanced or not in Java language.
One way is to create a counter variable which will be incremented as soon as I find out the opening bracket and decrement it when closing bracket is encountered. Based on the result, I can decide the result.
But this is not going to help for string like () i.e. not having any alpha numeric character between brackets.
Is there any way in which I can determine whether round brackets are balanced and there should be alpha numeric characters between these brackets.
In case brackets are empty i.e. no character between opening and closing brackets, it should throw an error.
You'll need a code similar to below one. It does use a Stack to track the number of opened/closed parantheses + remembers what was the last char occurence in order to track empty parantheses:
String test = "{TEST}(A){";
Stack<Integer> stack = new Stack<>();
boolean lastCharIsParantheses = false;
for (char c : test.toCharArray()) {
switch (c) {
case '{':
case '(': {
stack.push(1);
lastCharIsParantheses = true;
continue;
}
case '}':
case ')':
stack.pop();
if (lastCharIsParantheses) {
throw new RuntimeException("Empty parantheses");
}
}
lastCharIsParantheses = false;
}
if (!stack.empty()) {
throw new RuntimeException("Not matching number of opened/closed parantheses");
}
I'm trying to check if an expression is balanced in terms of its parentheses , my program should output the appropriate messages as follows: (I'm reading the expression from a file)
If for every ")" there is an "(" then it's balanced.
If there is a ")" with no "(" then the left parentheses is missing , and so on.
i worked out the code for the case of " (A+B) " and it prints balanced, but for the case of " (A+B))" it prints Balanced and Left missing and I can't seem to figure out what the problem is
here's the code:
(EDIT: I worked it out as a method, it works fine when the expression is balanced and when the right parenthesis is missing, but if the left one is missing it prints out "balanced") The problem is when it has a missing left parenthesis, the stack returned is empty, so that's why it prints "balanced" . I dont really know how to fix that case!
public static Stack isBalanced(String str) {
Stack s = new Stack();
char temp;
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) == '(') {
s.push(str.charAt(i));
} else if (str.charAt(i) == ')') {
if (!s.isEmpty()) {
temp = (char) s.pop();
}
}
}
return s;
}
This seems like an overly complex approach to the problem. You can simplify this a lot just by realizing that in this case you are only matching one possible pair so a simple count is enough.
Simply scan through the string checking each character. Increment a counter at each (, decrement it at each ).
If the counter ever falls below zero then you have an extra closing bracket. If you finish the scan and the counter is not zero then you have an extra opening bracket.
You're checking whether the stack isEmpty every single time you encounter a ) and printing "Balanced" the first time your count gets down to zero. You should only make that check at the very end (and you'll also need to make sure you never saw a stack underrun throughout).
I've solved the problem, in the end I had only 1 condition which was checking if the stack was not empty, and I didn't put a condition when the stack was not empty, so if the stack happened to be empty I will push the closing parentheses into it and in the main the appropriate message will be printed ( I forgot to add my mm in the code above)
if (!s.isEmpty()) {
temp = (char) s.pop();
}else{
s.push(str.charAt(i));
}
Then in the mm I'm checking whether my returned stack is empty or not and print the right messaged (balanced- left missing- right missing)
I created a method to basically detect white space characters. I go through a string and check each character for white space. If it is a white space character, I return true, and if it's not, I return false. However, I get a compilation error, stating "missing return statement". As I already have two return statements "true" and "false", I can't see why there is an error. Can you help me out or point me in the right direction? Thanks in advance.
public boolean isWhitespace()
{
for (int i=0; i<string.length(); i++)
{
if (Character.isWhitespace(i))
{
return true;
}
else
{
return false;
}
}
}
Imagine if string.length() were 0. What would get returned?
Also, note that this doesn't do what you stated, which is to go through a string and check each character. It actually isn't checking anything about the string at all because of your use of i. If it were checking the string, it still would only check the first character of the string. If that character is whitespace, true is immediately returned, and if not, false is immediately returned.
You are looping over the length of the String, yet trying to return inside that loop. The logic doesn't make sense.
Think about the problem you are trying to solve - do you want to test if a character is a whitespace, or if an entire String contains at least one whitespace character? For the latter:
boolean hasWhite = false;
for(int i=0; i < string.length(); i++)
{
if(Character.isWhitespace(string.charAt(i)))
{
hasWhite = true;
break;
}
}
return hasWhite;
EDIT: A much simpler approach, if you're into that sorta thing ;-) -
return string.contains(" ");
Here is what your code should look like:
public boolean isWhitespace(String string) { // NOTE: Passing in string
if (string == null) { // NOTE: Null checking
return true; // You may consider null to be not whitespace - up to you
}
for (int i=0; i < string.length(); i++) {
if (!Character.isWhitespace(string.charAt(i))) { // NOTE: Checking char number i
return false; // NOTE: Return false at the first non-whitespace char found
}
}
return true; // NOTE: Final "default" return when no non-whitespace found
}
Note that this caters for the edge cases of a blank (zero-length) string and a null string