stack dealing with recognizng string in language, java program [closed] - java

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
SO my program is about language L = {'w$w' : w is a possible empty string of characters other than $, w' = reverse(w)}
So when something like hod$doh is fed to the parameter of isINlanguage function it should return true, but my program just stops and hangs doesnt out put anything
import java.util.Stack;
public class Stacks
{
public static void main(String[] args){
boolean eval = isInLanguage("sod$dos");
System.out.println(eval);
}
static // astack.createStack();
boolean isInLanguage(String aString){
Stack<Character> aStack = new Stack<>();
int i = 0;
char ch = aString.charAt(i);
while (ch != '$') {
aStack.push(ch);
i++;
}
//Skip the $
++i;
// match the reverse of w
boolean inLanguage = true; // assume string is in language
while (inLanguage && i < aString.length()) {
char stackTop;
ch = aString.charAt(i);;
try {
stackTop = (char) aStack.pop();
if (stackTop == ch) {
i++;
} else {
// top of stack is not ch(Charecter do not match)
inLanguage = false; // reject string
}
} catch (StackException e) {
// aStack.poo() failed, astack is empty (first, half of Stirng
// is short than second half)
inLanguage = false;
}
}
if (inLanguage && aStack.isEmpty()) {
return true;
}
else{
return false;
}
}
}

You are not resetting the ch inside the while loop to the next character:
while (ch != '$') {
aStack.push(ch);
i++;
ch = aString.charAt(i); // Add this
}
Also, inside the try block, the cast is not necessary. The assignment:
stackTop = (char) aStack.pop();
... is better written as:
stackTop = aStack.pop();
BTW, you are really complicating your task, by using boolean variable, and try-catch blocks. Don't let the stack.pop() throw any exception. Rather, pop an element only if stack is not empty. Also, you can directly return as soon as you find the string doesn't matches the required language, so there is no need to boolean variable.
I would modify your method as:
static boolean isInLanguage(String aString){
Stack<Character> aStack = new Stack<>();
int i = 0;
char ch;
// This is simplified way to write your first while loop
// Read a character, move the index further, and test, all in single statement
while ((ch = aString.charAt(i++)) != '$') {
aStack.push(ch);
}
// Iterate till the stack is not empty
while (!aStack.isEmpty()) {
// Get next character in string, and pop an element from stack
// If they are not equal, return false
if (aString.charAt(i++) != aStack.pop()) {
return false;
}
}
// If we reach here, means stack is empty. Test if the index `i` has reached end of the string.
// If it reached the end of the string, return true, else return false (because there are still some characters to be processed).
return i == aString.length();
}
aString.charAt(i++) will get the character at index i, and increment i thereafter.

Related

Is it possible in java to simplify the following if-statement?

I want to simplify this if-Statement and prevent writing "!='*'" three times. Is it possible?
if (i != '*' && j != '*' && k != '*')
use arrays:put all elements into the array, traverse the array and judge。
List<String> list = new LinkedList<>(Arrays.asList(i,j,k));
if(list.stream().noneMatch("*"::equals)){
}else{
}
use string: splice elements into a string
String temp = i+j+k;
if(temp.contains("*")){
}
I want to simplify this if-Statement and prevent writing "!='*'" three times.
Here is a solution that simplifies the readability and intent.
First, make a simple, obvious method with a clear name (bonus: this is easy to write unit tests around):
private static boolean isValid(char i) {
return i != '*';
}
Then in your calling code, do this:
if (isValid(i) && isValid(j) && isValid(k)) {
// do things if all are valid
}
You can further improve the readability by making a single method which checks isValid() for an array of characters:
private static boolean allAreValid(char[] chars) {
for (char ch : chars) {
if (!isValid(ch)) {
return false;
}
}
return true;
}
Then your calling code becomes really clear, not just the steps but also the intent – proceed with the body of the if statement only if the characters are all valid.
char[] chars = {i, j, k};
if (allAreValid(chars)) {
// do things if all are valid
}
Yes it is possible to omit writing !='*' three times but the method will be still longer one. I would suggest to use the method which you have written in your question but if you really want to try something other out (maybe out of curiosity), you can do this:
char ch[] = {i,j,k}; /*I hope the variables i,j,k in question are char type*/
boolean flag = false;
for(int t = 0; t < ch.length; t++){
if(ch[t] != '*')
flag = true;
else{
flag = false;
break;
}
}
if(flag){
//Tasks to do...
}
Writing this much is a tedious job. Thus, if (i != '*' && j != '*' && k != '*') is the most optimised one. So I would recommend using it.

Given two strings S and T, return if they are equal when both are typed into empty text editors. # means a backspace character

Example 1:
Input: S = "ab#c", T = "ad#c"
Output: true
Explanation: Both S and T become "ac".
Example 2:
Input: S = "ab##", T = "c#d#"
Output: true
Explanation: Both S and T become "".
Example 3:
Input: S = "a##c", T = "#a#c"
Output: true
Explanation: Both S and T become "c".
Example 4:
Input: S = "a#c", T = "b"
Output: false
Explanation: S becomes "c" while T becomes "b".
class Solution {
public boolean backspaceCompare(String S, String T) {
Stack<Character> stack1 = new Stack<Character>();
Stack<Character> stack2 = new Stack<Character>();
for(int i=0;i<S.length();i++){
if(S.charAt(i)!='#'){
stack1.push(S.charAt(i));
}else{
stack1.pop();
}
}
for(int j =0;j<T.length();j++){
if(T.charAt(j)!='#'){
stack2.push(S.charAt(j));
}else
stack2.pop();
}
if(stack1==stack2)
return true;
return false;
}
}
my output is false and answer should be true why is this not working?
The first mistake is pushing all the characters on the stack outside of the if statement.
Also you should check if stack is empty before removing items from it.
Otherwise EmptyStackException is thrown.
// stack1.push(S.charAt(i)); <-- remove this line
if (S.charAt(i)!='#') {
stack1.push(S.charAt(i));
}else if (!stack1.isEmpty()) { // <-- add this check
stack1.pop();
}
The second mistake is you can't use == to compare the contents of two stacks, use .equals method instead:
if(stack1.equals(stack2))
Answer by Joni correctly addresses the errors in the code, however there are some other issues I'd like to address:
You should use a helper method to eliminate repeating the same code.
You should use Deque instead of Stack. The javadoc says so.
Instead of using Stack/Deque, I'd recommend using StringBuilder, to prevent having to box the char values.
Something like this:
public boolean backspaceCompare(String s, String t) {
return applyBackspace(s).equals(applyBackspace(t));
}
private static String applyBackspace(String s) {
StringBuilder buf = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) != '#')
buf.append(s.charAt(i));
else if (buf.length() != 0)
buf.setLength(buf.length() - 1);
}
return buf.toString();
}
Your idea works, but it's expensive and unnecessary to copy the strings into stacks. If you work backwards from the end, no extra storage is necessary:
//given the string length or a valid character position, return
//the position of the previous valid character, or -1 if none
public static int previousCharPos(String s, int pos)
{
int bs=0; // number of backspaces to match
while(pos>0) {
--pos;
if (s.charAt(pos)=='#') {
++bs;
} else if (bs <= 0) {
return pos;
} else {
--bs;
}
}
return -1;
}
public static boolean backspaceCompare(String S, String T)
{
int spos = previousCharPos(S,S.length());
int tpos = previousCharPos(T,T.length());
while(spos >= 0 && tpos >= 0) {
if (S.charAt(spos) != T.charAt(tpos)) {
return false;
}
spos = previousCharPos(S,spos);
tpos = previousCharPos(T,tpos);
}
return spos == tpos;
}

Write a method that takes a string of curly brackets and returns true if the brackets match up and false if they don’t

I was working on this problem in CodeHS, where I have to write a method that takes a string of curly brackets and returns true if the brackets match up and false if they don’t.
this is my coding so far, and I do not know what to do when there's same amount of left curly bracket and right curly bracket, but those just does not match like ( }}{{ ) this for an example.
public boolean bracketsMatch(String brackets)
{
boolean result = true;
int leftCtr = 0 ; //"{";
int rightCtr =0 ; // "}";
int count = 0;
for (int i=0; i<brackets.length(); i++)
{
char c = brackets.charAt(i);
if ( c == '{')
{
leftCtr++;
}
if (c =='}')
{
rightCtr++;
}
}
if (rightCtr==leftCtr)
{
result= true;
}
else
{
return false;
}
return result;
}
Thank you
I think the easiest way is just to keep a single count, which you increment for an open bracket and decrement for a closed bracket. then use the following rules:
If the count is ever below 0, then it is invalid (i.e. a closing bracket that was never opened)
If at the end the count is not 0, then it is invalid (i.e. too many open brackets)
With that in mind your code would look like this:
public boolean bracketsMatch(String brackets)
{
int count = 0;
for (int i=0; i< brackets.length(); i++)
{
char c = brackets.charAt(i);
if ( c == '{')
{
count++;
}
else if (c =='}')
{
count--;
}
// Process the first rule.
// Check if we have a negative count (i.e. close bracket without a matching opener).
// If we have a negative then we know the string is invalid, so we can stop processing and return (false) early.
if (count < 0)
{
return false;
}
}
// Process the second rule.
// If we got this far then we know there are no invalid close brackets, so now we need to just check to make sure we didn't have too many open brackets.
// Return true if everything matching (i.e. 0), otherwise false.
return count == 0;
}
Already Musefan gave a brilliant answer. Here is an another implementation. Using Stack Data Structure.
public static boolean isBracketMatch(String str) {
Stack<Character> stack = new Stack<>();
char c;
for (int i = 0; i < str.length(); i++) {
c = str.charAt(i);
if (c == '{')
stack.push('}');
else if (c == '}') {
if (!stack.empty() && stack.peek() == c)
stack.pop();
else
return false;
}
}
return stack.empty();
}

Trying to get the code to check if there are even brackets

I am currently trying to come up with a code that will scan a string
and check to see if there is an even number of open and closing brackets on each line. If so, it would return true. (Excuse me for the incorrectness in formatting but I could not get the examples to properly take shape unless I identified it as code)
{} // The code would return true
{{}}
{}{}
{{{}{{}}}}
} // The code would return false
{}
}}{
{{{}{}
What I tried so far:
public boolean bracketsMatch(String brackets)
{
int lb = 0;
int rb = 0;
int i = 0;
while (brackets.charAt(i) == '{' || brackets.charAt(i) == '}' || brackets.charAt(i) == '')
{
if (brackets.charAt(i) == '{')
{
lb += 1;
}
if (brackets.charAt(i) == '}')
{
rb += 1;
}
if (brackets.charAt(i) == '')
{
if (lb / rb == 2)
{
// Is it possible to get the code scan the next line to next line?
// need an extra statement here for ^^ before I can place the if statement below
if (bracket.charAt(i + 1) == '')
{
return true;
}
}
else
{
return false;
}
}
i++
}
}
I apologize in advance for any experienced programmers as this would be an inefficient nightmare. I am relatively new to programming in general. I attempted to have the code check for the number of left brackets (lb) and right brackets (rb). Whenever the code came to an empty string, it would divide lb by rb. If the code did not equal 2, the code would return false. I probably have more than a dozen errors in this code, but I was wondering if there was any way to have the code go onto the next line to scan the next set of brackets. Thanks for any help in advance.
EDIT 1:
public boolean bracketsMatch(String brackets)
{
int balance = 0;
for (int i = 0; i < brackets.length(); i++)
{
char value = brackets.charAt(i);
if (value == '{')
{
balance += 1;
}
else if (value == '}')
{
balance -= 1;
}
}
if (balance != 0)
{
return false;
}
else
{
return true;
}
}
This won't compile, as '' is an invalid character literal:
if (brackets.charAt(i + 1) == '')
And your current approach of counting opening and closing brackets,
and checking the value of lb / rb won't yield the right result.
You don't need to count the right brackets. You only need to count the open brackets, and reduce that count as they get closed.
Here's a sketch of an algorithm you can use,
I hope to not spoil the exercise:
For each character in the string
If it's an open bracket, increment the count
If it's a close bracket
If the open count is 0, there's nothing to close, so they are not balanced, we can stop
Decrement the count
After all characters, if the open count is 0, the brackets are balanced
As an additional code review note, this is bad in many ways:
if (brackets.charAt(i) == '{') {
// ...
}
if (brackets.charAt(i) == '}') {
// ...
}
What's bad:
Calling brackets.charAt(i) repeatedly is unnecessary if the result will always be the same. Call it once and save the result in a variable.
The two if conditions are exclusive: if the first is true, the second won't be true, so it's pointless to evaluate it. The second condition should be if else instead of if. And instead of an if-else chain, a switch could be more interesting here.
Instead of calling the string brackets, it would be better to call it something more general. What if the actual input is "{something}"? Then it contains more than just brackets, but the algorithm would work just the same. Calling it brackets is misleading.
Alternative way to do
You can use Java Stack class [As it represent the List-In-First-Out stack of object].You can use the push and pop method of Stack class. Here is the implementation.
public class BracketMatching {
public static boolean bracketMatch(String input){
Stack<Character> st = new Stack<>();
for(char c : input.toCharArray()){
if( c == '{')
st.push(c);
else if(c == '}'){
if(st.isEmpty())
return false;
st.pop();
}
}
if(st.isEmpty())
return true;
return false;
}
public static void main(String[] args){
String input1 = "{}{{}}{}{}{{{}{{}}}}";
String input2 = "}{}}}{{{{}{}";
System.out.println(bracketMatch(input1));
System.out.println(bracketMatch(input2));
}
}

Why does else if( 2 > 1) { System.out.println(" hello") ;} is not working? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
Problem in infix to postfix conversion
at the point when value fetched is '-' then the compiler does not enter at else-if block (last case)
package com.conversion;
import java.util.Scanner;
public class mainclass {
private static Scanner sc;
public static void main(String[] args) {
// TODO Auto-generated method stub
String s;
sc = new Scanner(System.in);
System.out.println("Enter a complete expresion");
s= sc.next();
stackop ob = new stackop();
System.out.println("YOUR PROVIDED input expression is :"+s);
//System.out.print(" Equivalent postfix notation is : ");
System.out.println("\n\n");
ob.postfix(s);
}
}
class stackop{
char stack1[]=new char[50];
int top;
void push(char ch)
{
top++;
stack1[top]=ch;
System.out.println(" element pushed is: "+ch);
System.out.println("----- current value of top is after push overs : "+top+" -------");
}
char pop(){
char ch;
ch= stack1[top];
//System.out.println("current value of top is : "+top);
System.out.println(" element popped is: "+ch);
--top;
System.out.println("----- current value of top is after pop overs : "+top+" -------");
return ch;
}
boolean isalpha(char a)
{
if((a>='a' && a<='z')||(a>=0 && a<=9))
return true;
else
return false;
}
boolean operator(char ch)
{
if(ch=='/'||ch=='*'||ch=='+'||ch=='-')
return true;
else
return false;
}
int prech(char ch){
switch(ch)
{
case '-': return 1;
//break;
case '+': return 1;
//break;
case '/': return 2;
//break;
case '*': return 2;
}
return 0;
}
void postfix(String str)
{
char otop=0;
char[] output = new char[str.length()+1];
for(int i=0 ; i<str.length();i++)
{
char ch=str.charAt(i);
System.out.println("==========value fetched is "+ch+" ===========");
if(ch=='(')
push(ch);
else if(isalpha(ch))
{
System.out.println("elemnt inserted in output list is :"+ch);
output[++otop]=ch;
}
else if(ch == ')' )
{
char temp=0;
System.out.println(" a close bracket is encounterd ");
while((temp=pop())!='(')
{
output[++otop]=temp;
System.out.println("elemnt inserted in output list is :"+temp);
}
}
else if(operator(ch))
{
if(prech(stack1[top])==0||(prech(stack1[top])<=prech(ch))||(prech(stack1[top])=='('))
push(ch);
}
else if(prech(stack1[top]) > prech(ch))
{
System.out.println(" hahah here i come");
output[++otop]=pop();
push(ch);
}
}
while(top>0)
{
output[++otop]=pop();
System.out.println("elemnt inserted in output list is :"+output[otop]);
}
System.out.println("\n\nOUTPUT OF EXPRESSION IS : " );
for(int j=0;j<str.length();j++)
{
System.out.print(""+output[j]);
}
}
}
In this chunk of code:
else if(operator(ch))
{
if(prech(stack1[top])==0||(prech(stack1[top])<=prech(ch))||(prech(stack1[top])=='('))
push(ch);
}
else if(prech(stack1[top]) > prech(ch))
The operator(ch) method returns true for your operators, which means control flow never reaches the second else if. What you probably want to do is move it inside the first else if, as shown below:
else if(operator(ch))
{
if(prech(stack1[top])==0||(prech(stack1[top])<=prech(ch))||(prech(stack1[top])=='('))
{
push(ch);
}
else if(prech(stack1[top]) > prech(ch)) { ... }
}
The title and the question do not have anything in common, also you should format your code. Nonetheless here's my answer to the question which you probably would've asked had you written an appropriate title.
Well actually 0 != '0' in programming, because '0' is translated to it's integer value which in ASCII is 48 and the comparison is between 0 and 48.
So your isalpha method should look like this:
boolean isalpha(char a)
{
if((a>='a' && a<='z')||(a>='0' && a<='9'))
return true;
else
return false;
}
Also, there are these neat little methods with which you don't need to check characters' ASCII code to compare them. I personally prefer this approachh as it is more simple and concise. It would look like this:
boolean isalpha(char a)
{
return Character.isDigit(a) || Character.isAlphabetic(a);
}

Categories

Resources