So what I have is this slightly modified version of a code that's here a hundred times over for Java Stack Balancing.
import java.util.Stack;
public class Main {
public static String testContent = "{(a,b)}";
public static void main(String args[])
{
System.out.println(balancedParentheses(testContent));
}
public static boolean balancedParentheses(String s)
{
Stack<Character> stack = new Stack<Character>();
for(int i = 0; i < s.length(); i++)
{
char c = s.charAt(i);
if(c == '[' || c == '(' || c == '{' )
{
stack.push(c);
}else if(c == ']')
{
if(stack.isEmpty()) return false;
if(stack.pop() != '[') return false;
}else if(c == ')')
{
if(stack.isEmpty()) return false;
if(stack.pop() != '(') return false;
}else if(c == '}')
{
if(stack.isEmpty()) return false;
if(stack.pop() != '{') return false;
}
}
return stack.isEmpty();
}
}
What I'd like to do is customize the output such that it would output something like "balanced" or "imbalanced" instead of true/false. Trying to replace return false; with a System.println containing 'balanced' gives me a whole lot of output lines I didn't want. Been searching around here for about an hour and some change and couldn't quite find the answer I was looking for. Any insight?
You could use something like
System.out.println(balancedParentheses(testContent) ? "balanced" : "imbalanced");
OR if you want a method that returns a String wrap the logic in another method
String isBalanced(String expression) {
return balancedParentheses(expression) ? "balanced" : "imbalanced"
}
and in main()
System.out.println(isBalanced(testContent));
Also you could write the code something like this
public static boolean balancedParentheses(String s) {
Stack<Character> stack = new Stack<Character>();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '[' || c == '(' || c == '{') {
stack.push(c);
} else if (c == ']' || c == ')' || c == '}') {
if (stack.isEmpty() || !matches(stack.pop(), c))
return false;
}
}
return stack.isEmpty();
}
private static boolean matches(char opening, char closing) {
return opening == '{' && closing == '}' ||
opening == '(' && closing == ')' ||
opening == '[' && closing == ']';
}
Related
I have the following code for the solution of Hackerrank.
public static void main(String[] args) {
System.out.println(isBalanced("{(([])[])[]}"));
}
public static String isBalanced(String s) {
Stack<Character> stack = new Stack<>();
stack.push(s.charAt(0));
for (int i = 1; i < s.length(); i++) {
Character c = s.charAt(i);
Character cStack = stack.peek();
if (cStack == '{' && c == '}'
|| cStack == '[' && c == ']'
|| cStack == '(' && c == ')') {
stack.pop();
} else {
stack.push(c);
}
}
if (stack.isEmpty())
return "YES";
return "NO";
}
Although the code seems to working without any problem, it throws the following error on the Hackerrank page. I already test the input in my local IDE as it is {(([])[])[]}, but I am not sure if I need to get the last element (it maybe due to getting it via Character cStack = stack.peek(); and then stack.pop();.
So, could you please have a look at and test this code on Hackerrank page and let me know what is wrong?
Update:
public static String isBalanced(String s) {
Stack<Character> stack = new Stack<>();
stack.push(s.charAt(0));
for (int i = 1; i < s.length(); i++) {
Character c = s.charAt(i);
if (c == '{' || c == '[' || c == '(') {
stack.push(c);
} else if (stack != null) {
Character cStack = stack.peek();
if (cStack == '{' && c == '}'
|| cStack == '[' && c == ']'
|| cStack == '(' && c == ')') {
stack.pop();
}
}
}
if (stack.isEmpty())
return "YES";
return "NO";
}
Before calling stack.peek(), you need to check if the stack is empty or not. Calling pop() or peek() on an empty stack will raise an error.
If the current character is an opening bracket, you don't even need to check the stack top. If it is a closing bracket, then check if the stack is empty or not first. If it is, return false. Otherwise compare the top character and make a decision.
I have to solve this exercise and I am pretty new to coding. The task is:
In this problem, the input to your program is an array of N characters, each of which is either (, ), [ or ], and your program must return true if the parentheses are properly matched, and false if they are not.
The code works and solves all the tests correct, but it is to slow to pass overall and I can't figure out why. What can I do to improve the speed of the code? Thank in advance.
public class Dyck {
public boolean checkParentheses(ArrayList<Character> input) {
Stack<Character> s = new Stack<>();
Stack<Character> s2 = new Stack<>();
for(var c : input){
s.add(0, c);
}
Character c2;
Character c = s.pop();
if (c != ')' && c != ']') {
s2.add(c);
}
var size = s.size();
for (int i = 0; i < size; ++i) {
c = s.pop();
if (c == '[' || c == '(') {
s2.add(c);
}
if (c == ')') {
if (s2.isEmpty()) {
return false;
}
c2 = s2.pop();
if (c2 != '(') {
return false;
}
}
if (c == ']') {
if (s2.isEmpty()) {
return false;
}
c2 = s2.pop();
if (c2 != '[') {
return false;
}
}
}
if (s.isEmpty() && s2.isEmpty()) {
return true;
}
return false;
}
class Solution{
static boolean ispar(String x){
char [] arr = x.toCharArray();
int length = arr.length;
Stack<Character> stack = new Stack<>();
boolean isBalanced = true;
if(arr[0] == '}' || arr[0] == ')' || arr[0] == ']'){
isBalanced = false;
}
else{
for(int i=0; i<length; i++){
char bracket = arr[i];
if(bracket == '{' || bracket =='(' || bracket == '['){
stack.push(bracket);
}
else if(!stack.empty() &&
((char) stack.peek() == '(' && (bracket == ')'))
|| ((char) stack.peek() == '{' && bracket == '}')
|| ((char) stack.peek() == '[' && bracket == ']')
){
stack.pop();
}
else{
isBalanced = false;
}
}
if(stack.empty()){
isBalanced = true;
}
else{
isBalanced = false;
}
}
return isbalanced;
}
}
I am learning Stack data structure. And this is the first problem I am trying to solve but it is giving me this exception :
Exception in thread "main" java.util.EmptyStackException
at java.base/java.util.Stack.peek(Stack.java:102)
at Solution.ispar(File.java:57)
at Driverclass.main(File.java:23)
Here's an attempt to correct your code without changing your core attempt:
import java.util.Stack;
class Solution {
public boolean isBalancedBrackets(String str) {
char[] arr = str.toCharArray();
Stack<Character> stack = new Stack<>();
if (arr[0] == '}' || arr[0] == ')' || arr[0] == ']') {
return false;
} else {
for (char bracket : arr) {
if (bracket == '{' || bracket == '(' || bracket == '[') {
stack.push(bracket);
} else if (!stack.empty() &&
(bracket == ')' && stack.peek() == '(' ||
bracket == '}' && stack.peek() == '{' ||
bracket == ']' && stack.peek() == '[')) {
stack.pop();
} else {
return false;
}
}
}
return stack.empty();
}
}
Changes:
Removed the redundant isBalanced variable, you can just return immediately when you detect a mismatch.
For your else-if statement you need to group all the or conditions together, with one set of parentheses. This is the reason you are getting the EmptyStackException. Since you only want to check any of the three conditions if the stack is not empty.
Renamed method.
Also, consider using a Deque over a Stack in the future.
If you want to ommit letters in #Sash Sinha Solution you could add a new field:
private static Set<Character> bracketSet = Set.of('(', ')', '{', '}', '[', ']');
and the method:
public static boolean ommitLetters(Character chr) {
return bracketSet.contains(chr);
}
to implement it inside the loop:
...
for (char bracket : arr)
if (ommitLetters(bracket)) {
if (bracket == '{' || bracket == '(' || bracket == '[') {
stack.push(bracket);
} else if (!stack.empty() && (bracket == ')' && stack.peek() == '('
|| bracket == '}' && stack.peek() == '{' || bracket == ']' && stack.peek() == '[')) {
stack.pop();
} else {
return false;
}
} else
continue;
...
# Sash Sinha - yes, using HashMap removes the requirement for the multi-or statements completely, ex:
public static <K, V> K getKeyFromMapByValue(Map<K, V> map, V value) {
for (Entry<K, V> entry : map.entrySet())
if (entry.getValue().equals(value))
return entry.getKey();
return null;
}
private static Set<Character> validParenthesisSet = Set.of('(', ')', '{', '}', '[', ']');
public static boolean areParenthesisPaired(String expression) {
Stack<Character> stack = new Stack<>();
Map<Character, Character> parenthesisPairs = new HashMap<>() {
private static final long serialVersionUID = 6725243592654448763L;
{
put('(', ')');
put('{', '}');
put('[', ']');
}
};
for (Character actualParenthesis : expression.toCharArray()) {
if (validParenthesisSet.contains(actualParenthesis))
if (parenthesisPairs.containsValue(actualParenthesis)) { // must catch only closed
Character oppositeParenthesis = getKeyFromMapByValue(parenthesisPairs, actualParenthesis);
if (stack.size() == 0 || stack.peek() != oppositeParenthesis)
return false;
stack.pop();
} else
stack.push(actualParenthesis);
}
if (stack.size() > 0)
return false;
return true;
}
import java.util.Stack;
import java.util.Scanner;
public class CheckValidLocationofParenthensies {
public static void main(String args[]) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter five data");
String input1 = scanner.next();
balancedParenthensies(input1);
}
public static boolean balancedParenthensies(String s) {
Stack<Character> stack = new Stack<Character>();
for(int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if(c == '[' || c == '(' || c == '{' ) {
stack.push(c);
if(c == '[') {
newvalueforforward(s,']', i);
}
if(c == '{') {
newvalueforforward(s,'}', i);
}
if(c == '(') {
newvalueforforward(s,')', i);
}
} else if(c == ']') {
if(stack.isEmpty() || stack.pop() != '[') {
newvalue(s,'[', i);
return false;
}
} else if(c == ')') {
if(stack.isEmpty() || stack.pop() != '(') {
newvalue(s,'(', i);
return false;
}
} else if(c == '}') {
if(stack.isEmpty() || stack.pop() != '{') {
newvalue(s,'{', i);
return false;
}
}
}
return stack.isEmpty();
}
public static void newvalueforforward(String userval,char value,int decremntval) {
for(int i = 0; i < userval.length(); i++){
StringBuilder newvalue = new StringBuilder(userval);
int location=i;
newvalue.insert(i, value);
boolean valid= checkingnewvalueisValidorNot(newvalue, location);
location=i+1;
if(valid) {
System.out.println(newvalue+" "+""+location);
}
}
}
public static void newvalue(String userval,char value,int decremntval) {
for(int i = decremntval; i >= 0; i--){
StringBuilder newvalue = new StringBuilder(userval);
int location=decremntval - i;
newvalue.insert(decremntval - i, value);
boolean valid= checkingnewvalueisValidorNot(newvalue, location);
if(valid) {
System.out.println(newvalue+" "+""+location);
}
}
}
public static boolean checkingnewvalueisValidorNot(StringBuilder userval,int validpath) {
Stack<Character> stack = new Stack<Character>();
for(int i = 0; i < userval.length(); i++) {
char c = userval.charAt(i);
if(c == '[' || c == '(' || c == '{' ) {
stack.push(c);
} else if(c == ']') {
if(stack.isEmpty() || stack.pop() != '[') {
return false;
}
} else if(c == ')') {
if(stack.isEmpty() || stack.pop() != '(') {
return false;
}
} else if(c == '}') {
if(stack.isEmpty() || stack.pop() != '{') {
return false;
}
}
}
return stack.isEmpty();
}
}
Above is the code i have written to check whether input string contains all balanced brackets if it is not balanced then get missing bracket and place bracket in all index then again check whether string is balanced or not.
I got valid output but problem is between i bracket there should be a intergers
here is input and outputs
input missing outputs
{[(2+3)*6/10} ] {[](2+3)*6/10} 3 not valid(no numbres btn bracket)
{[(2+3)]*6/10} 8 valid
{[(2+3)*]6/10} 9 not valid(after * no number)
{[(2+3)*6]/10} 10 valid
{[(2+3)*6/]10} 11 not valid( / before bracket)
{[(2+3)*6/1]0} 12 not valid( / btn num bracket)
{[(2+3)*6/10]} 13 valid
i am failing to do proper validation to my output.
Before the bracket there may be:
number
closing bracket
After the bracket there may be:
operator
closing bracket
end of expression
(ignoring any whitespace)
Im working on a token iterator (valid tokens, "true, false, "true", "&", "!", "(", "false", "^", "true", ")".
The code is working, my question is about return values. I often run into this problem, I have return statements, but the final return statement throws off my result by duplicating the last return statement.
I think I know for sure the error lays within my placement of { and } and while i've learned they aren't necessary, since there's so many nested if's i feel they are necessary.
This seems to be a common problem to me and others ive worked with, does anyone have an idea of how to prevent this problem from happening? Thanks!
My code outputs:
line: [ ! BAD (true ^ false) % truelybad]
next token: [!]
next token: [(]
next token: [true]
next token: [^]
next token: [false]
next token: [)]
next token: [)]
and should output
next token: [!]
next token: [(]
next token: [true]
next token: [^]
next token: [false]
next token: [)]
public class TokenIter implements Iterator<String> {
ArrayList<String> token = new ArrayList<String>();
static int count = 0;
// input line to be tokenized
private String line;
// the next Token, null if no next Token
private String nextToken;
// implement
public TokenIter(String line) {
this.line = line;
}
#Override
// implement
public boolean hasNext() {
// System.out.println(count);
return count < line.length();
}
#Override
// implement
public String next() {
while (hasNext()) {
char c = line.charAt(count);
if (c == '!' || c == '!' || c == '^' || c == '(' || c == ')') {
token.add(Character.toString(c));
count++;
nextToken = Character.toString(c);
return nextToken;
} else if (c == 't' || c == 'T') {
count++;
c = line.charAt(count);
if (c == 'r') {
count++;
c = line.charAt(count);
}
if (c == 'u') {
count++;
c = line.charAt(count);
}
if (c == 'e') {
count++;
c = line.charAt(count);
}if (c == ' ' || c == '!' || c == '!' || c == '^' || c == '(' || c == ')'){
token.add("true");
nextToken = "true";
//count++;
return nextToken;
}
} else if (c == 'f' || c == 'F') {
count++;
c = line.charAt(count);
if (c == 'a') {
count++;
c = line.charAt(count);
}
if (c == 'l') {
count++;
c = line.charAt(count);
}
if (c == 's') {
count++;
c = line.charAt(count);
}
if (c == 'e') {
count++;
c = line.charAt(count);
}
if (c == ' ' || c == '!' || c == '!' || c == '^' || c == '(' || c == ')'){
token.add("false");
nextToken = "false";
// count++;
return nextToken;
}
} else if (c == ' ') {
count++;
} else {
count++;
}
}
return nextToken;
}
#Override
// provided, do not change
public void remove() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException();
}
// provided
public static void main(String[] args) {
String line;
// you can play with other inputs on the command line
if (args.length > 0)
line = args[0];
// or do the standard test
else
line = " ! BAD (true ^ false) % truelybad";
System.out.println("line: [" + line + "]");
TokenIter tokIt = new TokenIter(line);
while (tokIt.hasNext())
System.out.println("next token: [" + tokIt.next() + "]");
}
}
Problem with your code comes only when last digit is not a token.
Reason - You are checking hasNext() which is true it goes inside your code.You are not setting nextToken for this case so it uses your lask token and display it.
I updated your code to always return a value and check if value return is from token list then display otherwise ignore it.
public class test implements Iterator<String> {
static List<String> tokenList = Arrays.asList( "true", "&", "!", "(", "false", "^", "true", ")");
ArrayList<String> token = new ArrayList<String>();
static int count = 0;
// input line to be tokenized
private String line;
// the next Token, null if no next Token
private String nextToken;
// implement
public test(String line) {
this.line = line;
}
#Override
// implement
public boolean hasNext() {
// System.out.println(count);
return count < line.length();
}
#Override
// implement
public String next() {
while (hasNext()) {
char c = line.charAt(count);
if (c == '!' || c == '!' || c == '^' || c == '(' || c == ')') {
token.add(Character.toString(c));
count++;
nextToken = Character.toString(c);
return nextToken;
} else if (c == 't' || c == 'T') {
count++;
c = line.charAt(count);
if (c == 'r') {
count++;
c = line.charAt(count);
}
if (c == 'u') {
count++;
c = line.charAt(count);
}
if (c == 'e') {
count++;
c = line.charAt(count);
}if (c == ' ' || c == '!' || c == '!' || c == '^' || c == '(' || c == ')'){
token.add("true");
nextToken = "true";
//count++;
return nextToken;
}
} else if (c == 'f' || c == 'F') {
count++;
c = line.charAt(count);
if (c == 'a') {
count++;
c = line.charAt(count);
}
if (c == 'l') {
count++;
c = line.charAt(count);
}
if (c == 's') {
count++;
c = line.charAt(count);
}
if (c == 'e') {
count++;
c = line.charAt(count);
}
if (c == ' ' || c == '!' || c == '!' || c == '^' || c == '(' || c == ')'){
token.add("false");
nextToken = "false";
// count++;
return nextToken;
}
} else if (c == ' ') {
count++;
nextToken = null;
} else {
count++;
nextToken = null;
}
}
return nextToken;
}
#Override
// provided, do not change
public void remove() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException();
}
// provided
public static void main(String[] args) {
String line;
// you can play with other inputs on the command line
if (args.length > 0)
line = args[0];
// or do the standard test
else
line = " ! BAD (true ^ false) % truelybad ";
System.out.println("line: [" + line + "]");
test tokIt = new test(line);
while (tokIt.hasNext()) {
String s = tokIt.next();
if (s != null && tokenList.contains(s))
System.out.println("next token: [" + s + "]");
}
}
}
The underlying problem here is that your hasNext() method returns true not if there is another token in the String, but if it hasn't finished parsing the String yet.
So what happens is if you put in the String " ! ! true lotsofcrap ", then calling next() will return "!", then "!", then "true", then after that has been returned, there are no more tokens in the String, yet hasNext() still returns true.
What you might consider doing is having hasNext() parse through the string, but instead of returning the next String, return true only if it finds another token ahead of the current position. Keep in mind that in hasNext(), you do not want to directly increment count. Instead, make a local variable int something = count; at the beginning of hasNext() and use that. If you fix that, then the rest of your code SHOULD work just fine.