The method below takes in a string and a pattern and returns true if they match each other. A '.' matches 1 char and a '*' matches 0 or more (e.g. expMatch("abc", "a.c") should return true). I added a bunch of print statements to see where I went wrong and it seems like the if statement is being skipped even if the str.length() == 1.
I call it with System.out.println(expMatch("abc", "a*c"));
Here is the code:
public static boolean expMatch(String str, String pat)
{
if (str.charAt(0) == pat.charAt(0) || pat.charAt(0) == '.')
{
System.out.println("in if");
System.out.println(str.charAt(0));
System.out.println(pat.charAt(0));
System.out.println(str.length());
if (str.length() == 1)
return true;
expMatch(str.substring(1), pat.substring(1));
}
else if (pat.charAt(0) == '*')
{
System.out.println("in else");
System.out.println(str.charAt(0));
System.out.println(pat.charAt(0));
if (str.length() == 1)
return true;
if (str.charAt(0) == pat.charAt(1)) //val of * = 0
expMatch(str, pat.substring(1));
else if (str.charAt(1) ==pat.charAt(1))
expMatch(str.substring(1), pat.substring(1));
}
return false;
}
and the output is:
in if
a
a
3
in else
b
*
in if
c
c
1
false
Even if the length is 1 it skips the if? Any idea why?
P.S. I'm not looking for the solution, just why the if statement is being skipped.
You always return false from the method at the very end. You are calling expmatch recursively but never using the return value. The code comes in to the first if, recurses (because length is not 1) and upon returning will go to the final return statement which returns false.
You need to add a return before your expMatch() calls - because the false comes from your last line return false;
What happens is this:
you call expMatch() with the two Strings.
you enter the if clause
the if clause enters expMatch() recursively
you enter the else clause
the else clause enters expMatch() recursively
you enter the if clause again
you leave the expMatch() method
you leave the other expMatch method
false is returned
Your approach is logically incorrect even if you apply the fixes the others suggested. Try this test case:
System.out.println(expMatch("abddddc", "a*c"));
This is because when you encounter a * in the pattern, you have no way to know how many characters "to eat" from the search string.
To say the least, you need a loop somewhere, not just an if. Let me try to fix it for you (not sure if it's possible though, not sure if you always know which path to take, I mean in your recursion). Think some more about it. Here is another unpleasant test case:
System.out.println(expMatch("adddcac", "a*c"));
// the * needs to eat dddca (despite the c present in dddca),
// it should not stop recursing there at that c
I think you need some sort of full search here.
Just an if or a while loop is not good enough.
EDIT: Here is a fixed version with a bunch of nasty tests. I think this is called non-linear recursion (as it's not a single path you try). Not 100% sure though about that term.
public class Test055 {
public static void main(String[] args) {
// System.out.println(expMatch("abddddc", "a*c"));
System.out.println(expMatch("adcax", "a*c"));
System.out.println(expMatch("adcax", "a*c*"));
System.out.println(expMatch("adcacm", "*"));
System.out.println(expMatch("adcacmmm", "a*c"));
System.out.println(expMatch("adcacmmmc", "a*c"));
System.out.println(expMatch("adcac", "a*c"));
System.out.println(expMatch("adcacxb", "a*c.b"));
System.out.println(expMatch("adcacyyb", "a*c.b"));
System.out.println(expMatch("adcacyyb", "a*c*b"));
}
public static boolean expMatch(String str, String pat)
{
// System.out.println("=====================");
// System.out.println("str=" + str);
// System.out.println("pat=" + pat);
if (pat.length() == 0 && str.length() > 0) {
return false;
} else if (pat.length() == 0 && str.length() == 0) {
return true;
} else if (pat.charAt(0) == '.'){
return str.length() >= 1 && expMatch(str.substring(1), pat.substring(1));
}else if (pat.charAt(0) != '*'){
return str.length() >= 1 && pat.charAt(0) == str.charAt(0) && expMatch(str.substring(1), pat.substring(1));
}else{
// Now let's handle the tricky part
// (1) Look for the 1st non-star in pattern
int k=-1;
char ch = ' ';
for (int i=0; i<pat.length(); i++){
if (pat.charAt(i) != '*'){
k = i;
ch = pat.charAt(k);
break;
}
}
if (k==-1){
// (2A) only stars found in pattern, OK, any str matches that
return true;
}else{
// (2B) do full search now checking all
// possible candidate chars in str that
// match the char ch from pattern
for (int i=0; i<str.length(); i++){
if (str.charAt(i)==ch){
boolean b = expMatch(str.substring(i+1), pat.substring(k+1));
if (b) return true;
}
}
return false;
}
}
}
}
Related
I am trying to do a practice problem 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. If I'm passed the empty string, it needs to return true. We can also assume that the given string can have { and } in it or be empty.
Matching has to be in the correct order of pairs like "{}" not "}{"
These are examples of brackets matching:
{}
{}{}
{{}}
{{{}{{}}}}
These are examples of the brackets not matching:
{
}{
{{}
{{}}}{}
This is what I currently have (Keep in mind I'm relatively new to coding):
public boolean bracketsMatch(String brackets)
{
int count = 0;
if (brackets.length() % 2 == 1){
return false;
}
for(int i = 0; i < brackets.length(); i++){
if ((brackets.charAt(i)+"") == "{"){
count++;
} else if ((brackets.charAt(i)+"") == "}"){
count--;
}
if (count == -1){
return false;
}
}
return count == 0;
}
Inputs like this }{ and {}}{}{ this still dont return the right output.
Your logic works, but the way you're comparing characters is wrong: never use == to compare string values - it tests for reference equality (whether they are the same object). Try brackets.charAt(i) == '{' instead.
I was asked in a problem to make a static recursive method called search that searches for a character in a string and if it finds it prints it's location, if it doesn't, it returns -1
this is my code
public static int search(String s , char c)
{
boolean flag = true;
if (flag == false && s.length() == 0)
return -(s.length() + 1);
else
if (s.charAt(0) == c)
{
return 1;
}
else
{
flag = false;
return 1 + search(s.substring(1) , c);
}
I'm using a flag to see if it doesn't find it after coursing through all the string, it'll preform all of the string's length minus the string's length - 1,
But I always end up with a "StringIndexOutOfBoundsException" error. Where is that error located exactly? Thanks in advance! :D
edit: it works if i input a character that exists in the string like n in animal, but if i enter o and the string be animal , it'll give me the error.
edit 2: I got it to work by removing the flag and traversing the string from the last character, thanks everyone! :D
I guess the first index out of bounds will happen at else block s.substring(1)...
ex: s="a", c="b"
flag=true
if (flag == false && s.length() == 0) this will fail and go to else block
in else block, if (s.charAt(0) == c) , here "a"=="c" fails go to else block
in the inner else block, you have return 1 + search(s.substring(1) , c); this line will look for the String index
position 1, which is not available and throws
stringindexoutofboundsexception
Because of your recursion flag is always true so your first if will never be true.
It would help if flag would be a class member. In that case you need to reset the flag before each search.
But it would also leads to an exception if you invoke your search with an empty string. So I think you do not need the flag.
If you dint mind searching from the end of the string you can do this:
public static int search(String s , char c) {
if (s==null || s.length() == 0)
return -1;
else if (s.charAt(s.length()-1) == c)
{
return s.length();
} else {
int pos=search(s.substring(0,s.length()-1) , c);
return pos;
}
}
There are few small issues with your code.
flag is always true, so if conditions is always false:
boolean flag = true;
if (flag == false && s.length() == 0) // always false, even if
// s.length() is 0
Why do you need this flag variable? This assignment flag = false; has no effect by the way. You either need to change signature of your search method search(String s , char c, boolean flag) and pass it as 3rd param, or probably remove flag completely.
Second thing is that your function will return positive result for all strings will lengths more than 2 characters.
return 1 + search(s.substring(1) , c); and return -(s.length() + 1);. The last condition will be executed only if there are no more characters in the string (let's say we are not using flag variable).
if (s.length() == 0) // there are no more characters in the str
return -(s.length() + 1); // we return -1
But in this case we already have return 1 + search(s.substring(1) , c); which will lead to 1 + -(0+1). for search("a",'d'),
1 + 1 -(0+1) for search("ab",'d') and so on.
I hope this helps.
Error comes from return 1 + search(s.substring(1) , c); this line.
if you are searching for 'o', in the last iteration s=l and s.substring(1) doesn't exist
You have to move out the flag variable outside the method, as on every recursive call it is being set to true and hence the first if block will never get executed. loopCount will meet your purpose, you don't need to use flag variable.
static int loopCount =0;
public static void main( String[] args )
{
System.out.println(search("animal", 'o'));
}
public static int search(String s , char c)
{
loopCount++;
if (s.length() == 0){
return -loopCount;
}
else if (s.charAt(0) == c)
{
return 1;
}
else
{
return 1 + search(s.substring(1) , c);
}
}
I was practicing recursion problem. there are some type of questions wants you to count the number of specific characters in a String without loop.
What kind of method should I use? can anyone explain to me?
Here is the question:"Given a string, compute recursively (no loops) the number of lowercase 'x' chars in the string."
my code:
public int countX(String str) {
if(str.length()==0){
return 0;
}
if(str.charAt(0)=='x'){
return 1+ countX(str.substring(1));
}
return countX(str);
}
You're almost there, but you need to revise the case where the first letter in str isn't 'x'. What you are currently doing will cause infinite recursion because in the case where str.charAt(0) != 'x', you recursively call countX on str. However, str is still the same string that didn't have 'x' as its first letter, so it's going to call countX on str again and again and again, etc.. So the solution is to only call countX on str.substring(1) when its first letter isn't 'x' like so,
public int countX(String str) {
if(str.length()==0){
return 0;
}
if(str.charAt(0)=='x'){
return 1 + countX(str.substring(1));
}
else{
return countX(str.substring(1));
}
}
What your method was doing before
Let's say I called countX on "Hello", here's how the call stack trace would look like,
call countX("Hello")
"Hello".length() != 0 so we move on to the next condition
"Hello".charAt(0) != 'x' so we call countX("Hello")
call countX("Hello")
"Hello".length() != 0 so we move on to the next condition
"Hello".charAt(0) != 'x' so we call countX("Hello")
call countX("Hello")
"Hello".length() != 0 so we move on to the next condition
"Hello".charAt(0) != 'x' so we call countX("Hello");
.
.
.
infinite recursion
What the new solution does
call countX("Hello")
"Hello".length() != 0 so we move on to the next condition
"Hello".charAt(0) != 'x' so we call countX("ello")
call countX("ello")
"ello".length() != 0 so we move on to the next condition
"ello".charAt(0) != 'x' so we call countX("llo")
call countX("llo")
"llo".length() != 0 so we move on to the next condition
"llo".charAt(0) != 'x' so we call countX("lo");
call countX("lo")
"lo".length() != 0 so we move on to the next condition
"lo".charAt(0) != 'x' so we call countX("o");
call countX("o")
"o".length() != 0 so we move on to the next condition
"o".charAt(0) != 'x' so we call countX("");
call countX("")
"".length() == 0 so return 0
return 0
return 0
return 0
return 0
return 0
Notice how in the solution, we always have a way of getting to the base case (str.length()==0). Whereas before, there would be instances (when we encountered a letter that wasn't x) that would prevent the method from reaching the base case.
What kind of method should I use? can anyone explain to me?
one solution is to use a StringBuilder and simply delete the first character at each invocation of the method, eventually, you'll get to the base case and should output the correct result.
public int countX(String str) {
if(str.length() == 0) return 0;
StringBuilder builder = new StringBuilder(str);
if(str.charAt(0) == 'x'){
builder.deleteCharAt(0);
return 1 + counter(builder.toString());
}
builder.deleteCharAt(0);
return counter(builder.toString());
}
However, if you wish to proceed with your current solution, you'll need to replace this:
return countX(str);
with this:
return countX(str.substring(1));
the problem was that if the current character is not 'x' you simply ignored it and didn't simplify the problem towards the base case.
I understand your need. In below, you have the method you need to count recursively a character in a string.
static int countCharRecursively(String str, char ch){
if(str.indexOf(ch) != -1)
{
return countCharRecursively(str.substring(0, str.indexOf(ch)), ch)+
countCharRecursively(str.substring(str.indexOf(ch)+1),ch) + 1;
}
else{
return 0;
}
}
Here is a complete program you can run.
public class CountCharRecursivelyInString{
public static void main(String[] args){
String str = "hello the world";
char ch = 'l';
int nbr = countCharRecursively(str, ch);
System.out.println(ch + " : " + nbr);
}
static int countCharRecursively(String str, char ch){
if(str.indexOf(ch) != -1)
{
return countCharRecursively(str.substring(0, str.indexOf(ch)), ch)+
countCharRecursively(str.substring(str.indexOf(ch)+1),ch) + 1;
}
else{
return 0;
}
}
}
Question
We consider a word,w , to be beautiful if the following two conditions are satisfied:
No two consecutive characters are the same.
No two consecutive characters are in the following vowel set: a, e, i, o, u, y. Note that we consider y to be a vowel in this challenge.
For example:
The string batman is beautiful because it satisfies the given criteria; however, apple has two consecutive occurrences of the same letter (pp) and beauty has three consecutive vowels (eau), so those words are not beautiful.
My problem is when i am giving an input string "yes" it prints Yes but it should print No.
When i debugged the code using Intellij i see that
It is executing the code which is past return statement but the return statement is used to transfer control to the main function.
Solution
public class Coding {
int count = 0;
public static void main(String[] args) {
Coding obj = new Coding();
Scanner in = new Scanner(System.in);
String w = in .next();
boolean b = true;
char[] c = w.toCharArray();
for (int i = 0; i < c.length - 2; i++) {
b = obj.check(i, c); //recursive function
if (c[i] == c[i + 1]) {
b = false;
break;
}
if (!b) {
System.out.println("No");
break;
}
}
if (c[c.length - 2] == c[c.length - 1]) //check.for.the.remaining.chars
System.out.println("No");
else if (b) {
System.out.println("Yes");
}
}
public boolean check(int i, char[] c) {
if (c[i] == 'a' || c[i] == 'e' || c[i] == 'i' || c[i] == 'o' || c[i] == 'u' || c[i] == 'y') {
count++;
if (count == 2) {
return false; // code following this statement are executing
}
check(i + 1, c);
}
count = 0;
return true;
}
}
You are making a recursive call, but you are ignoring the results of that call!
That doesn't make sense. Either that call is valid, then you should return whatever comes back. Or the recursion doesn't "belong" there, then you should rework the complete method!
Beyond that: although recursive solution often look elegant, those contests focus on optimal performance. Meaning: rather use a single loop to iterate that string once.
Hint: The problem appears to be with method count. It always returns true to main method. If any recursive call returns false, is it being propagated back to main method?
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));
}
}