Link to home
Start Free TrialLog in
Avatar of gudii9
gudii9Flag for United States of America

asked on

string contains xx

Hi,
I am trying below challenge
http://codingbat.com/prob/p194667
I wrote as below

int countXX(String str) {
  int count=0;
  for(int i=0;i<str.length();i++){
  str.contains("xx");
  count=count+1;
  }
  return count;
}

Open in new window

It is failing below scenarios
Expected      Run            
countXX("abcxx") → 1      5      X         
countXX("xxx") → 2      3      X         
countXX("xxxx") → 3      4      X         
countXX("abc") → 0      3      X         
countXX("Hello there") → 0      11      X         
countXX("Hexxo thxxe") → 2      11      X         
countXX("") → 0      0      OK         
countXX("Kittens") → 0      7      X         
countXX("Kittensxxx") → 2      10      X         


How to fix and improve my code. Please advise
Avatar of Russ Suter
Russ Suter

int countXX(String str) {
  int count = 0;
  for (int i = 0; i < str.length()-1; i++) {
    if (str.substring(i, i+2).equals("xx")) count++;
  }
  return count;
}

Open in new window

Russ,

I'm pretty sure gudii9 could click the "Show Solution" button, too, if he wanted to.
Here's one take :

int countXX(String str) {

  int count=0;
  
  for (int i=0;i<str.length()-1;i++){
  
         if (str.charAt(i)== 'x' && str.charAt(i+1)== 'x'){count++;}
  }
    
  return count;
}

Open in new window

Here's my minimal solution...
int countXX(String str) {
  int count = 0;
  for(int from = 0; (from = str.indexOf("xx", from) + 1) > 0; count++);
  return count;
}

Open in new window

Avatar of gudii9

ASKER

from = str.indexOf("xx", from) + 1
what is meaning of above line. Please advise. Why we initialized 'from' and checking id string index of xx +1 greater than zero erc.
Please advise
'from' is the index position from where the indexOf function starts to look for the "xx" substring. 'from' steps to where it finds each incidence of the "xx" substring during the loop, and because it only stops when it finds two "xx"s together, it does not move through the redundant characters, and therefore when two lots of "xx" are in different parts of the search string, 'from' jumps to their index, making it more efficient than a fully exhaustive string iteration. If indexOf() finds no more "xx"s, (or never finds any to begin with), then count doesn't get incremented, and the method returns the number that it did find during the loop.

mccarl's method is somewhat more 'professional-level', and more powerful because it eschews irrelevant parts of the search string, and syntactically slightly more difficult construction than the standard loop concepts you see more generally, such as the one I posted, or, indeed, the suggested one in codingbat.

You can see how mccarl has thought through the requirements of the process to the ultimate level here.
Avatar of gudii9

ASKER

for(int from = 0; (from = str.indexOf("xx", from) + 1) > 0; count++);

why we need +1 in above statement.
Please advise
Avatar of gudii9

ASKER

int countXX(String str) {
  int count=0;
  for(int i=0;i<str.length()-1;i++){
  str.substring(i,i+2).equals("xx");
  count=count+1;
  }
  return count;
}

Open in new window


Why some test cases are failing and some passing when i write as above
Expected      Run            
countXX("abcxx") → 1      4      X         
countXX("xxx") → 2      2      OK         
countXX("xxxx") → 3      3      OK         
countXX("abc") → 0      2      X         
countXX("Hello there") → 0      10      X         
countXX("Hexxo thxxe") → 2      10      X         
countXX("") → 0      0      OK         
countXX("Kittens") → 0      6      X         
countXX("Kittensxxx") → 2      9      X         


for(int i=0;i<str.length()-1;i++){

what is the importance of '-1' in above statement. please advise
why we need +1 in above statement.
The  + 1  makes the code start looking from the NEXT character once it has found "xx" somewhere. If it didn't have the  + 1  it would keep find the same "xx" over and over again and it would be in an infinite loop.

Why some test cases are failing and some passing when i write as above
Some are passing out of sheer coincidence. Your code simply calculates the length of the string - 1. Look at the test cases... the first example has 5 characters and your code returns 4, the second example has 3 characters and your code returns 2.

The count=count + 1 line gets executed every time around the loop; it's not dependant on anything. And your that calls the ".equals()" method does nothing with the return value (it may as well not be there at all).

You need an if statement in there to check the result of .equals and so that count is NOT just updated every time through the loop.

what is the importance of '-1' in above statement.
The  - 1  is there because you don't need to check the LAST character of the string. Since it is only ONE character, it can NEVER be equal to "xx" as that is TWO characters.
what is the importance of '-1' in above statement. please advise

 . . . and, it has been a frequent area of doubt in your questions about the indexing situation. You will have to make a DETERMINED effort to *remember* that arrays (such as a String is (because it is just an array of chars actually)) ALWAYS start at 0. Therefore to make any for loops and other loops start at the beginning - which is character (or element) ZERO, it follows that the last character (or element) index number - POSITION - is going to be the length of that variable *MINUS 1*

This idea is never going to go away in Java, and I would say that unless and until you absorb this fact fully, you are going to waste a whole lot of your time.

------------

String s = "ABCD";
s.length() is 4.

**BUT** in a loop like this :
 for(int position=0;position<s.length();position++){//blah blah}

THE LOOP WILL ONLY KEEP RUNNING while 'position' is less than 4. That means the last iteration will set 'position' to 3, and index 3 is the LAST character in string s. Like this :

A = s.charAt(0)  B = s.charAt(1)  C= s.charAt(2) and D = s.charAt(3)

You can see that the letters ABCD are each taken care of by the index positions 0-3.
Avatar of gudii9

ASKER

for(int from = 0; (from = str.indexOf("xx", from) + 1) > 0; count++);


The  + 1  makes the code start looking from the NEXT character once it has found "xx" somewhere. If it didn't have the  + 1  it would keep find the same "xx" over and over again and it would be in an infinite loop.

How it increments 'from' (middle part). I see count only has increment(last part) not like from++. Please advise
'from' is assigned to 0 the first time, OK?

THEN on each subsequent iteration of the for loop, IF the search found "xx", then 'from' would be incremented to that index position  :

(from = str.indexOf("xx", from) + 1)

PLUS 1.

so in plain English, the above line says : from = the-position-at-which-you-found-"xx"-but-you-MUST-start-looking-from-position-'from' (which to begin with was 0).

AT THAT POINT, dear JVM, because you found "xx", at a CERTAIN position, please now add "1" to the position at which you found "xx", and put it into (overwrite the value in) the variable 'from', so that when the loop returns for another iteration, it can't find the one it just found again, because it MUST start looking from the new 'from' position, which is one more than where it found the last "xx".
SOLUTION
Avatar of CPColin
CPColin
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
and with that you'd have to do "return count+1" if I am not mistaken?
Avatar of gudii9

ASKER

int countXX(String str) {
int from = str.indexOf("xx") + 1;

while (from > 0)
{
   from = str.indexOf("xx", from) + 1;
   count++;
}
  return count+1;
}

Open in new window


i wrote as above getting error

Compile problems:


Error:      count++;
      ^^^^^
count cannot be resolved

please advise
Avatar of gudii9

ASKER

for(int from = 0; (from = str.indexOf("xx", from) + 1) > 0; count++);
Below statement I thought will check the 'xx' is present at position of 'from' or not present
str.indexOf("xx", from)

http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#indexOf(int,%20int)

indexOf
public int indexOf(int ch,
          int fromIndex)
Returns the index within this string of the first occurrence of the specified character, starting the search at the specified index.

but based on below explanation i am not clear if it increments to index posistion?

IF the search found "xx", then 'from' would be incremented to that index position  :
Error:      count++;
       ^^^^^
 count cannot be resolved

CPColin was partially abstracting - obviously you need to declare the variable before you can use it, which you haven't done.
Below statement I thought will check the 'xx' is present at position of 'from' or not present

str.indexOf("xx", from)

It does check that it is present - starting at position 'from'.
Please put these two amended lines of mccarl's code into the appropriate place in your code :

countXX("xxabcdxxxxxx");
for(int from = 0; (from = str.indexOf("xx", from) + 1) > 0; count++){System.out.println(from);}

Open in new window


To save you doing that if you are busy, I can tell you that it will print out :

1
7
8
9
10
11

which are the positions **+1** in which it finds "xx", and which are the values held by 'from'.

Now you are going to ask why the numbers above don't start at 0 and end at 10. The reason for that is that when str.indexOf("xx",from) first executes, 'from' IS zero. But it is immediately incremented by 1, so that by the time the printout is done for that loop iteration, 'from' holds the value 1, not zero.

OK?

But of course the point of this is that you can see that the characters at positions 2,3,4,5 and 6 (or strictly speaking, positions 1,2,3,4 and 5 according to array indexation protocol), ARE SKIPPED OVER in the search *. How is that? Well as has been said, because 'from' is incremented by 1, the loop CAN NEVER FIND AGAIN the previous pair of "xx"s that it just found, because the start position has moved on. QED. And O&O.

(* = this is true as far as we are concerned here in Java; but 'under the hood', the native code will be iterating the entire String, and only returning a found value to the 'from' variable, for our higher-level Java purposes).
Avatar of gudii9

ASKER

package eePackage;

public class Test15 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int howMany= countXX("axxbcxxeexddxr");
		System.out.println("number is--->"+howMany);

	}
	
	static int countXX(String str) {
		int from = str.indexOf("xx") + 1;
        int count=0;
		while (from > 0)
		{
		   from = str.indexOf("xx", from) + 1;
		   count++;
		}
		  return count;
		}

}

Open in new window


I got correct output as
number is--->2

all test cases are passing as well
Expected      Run            
countXX("abcxx") → 1      1      OK         
countXX("xxx") → 2      2      OK         
countXX("xxxx") → 3      3      OK         
countXX("abc") → 0      0      OK         
countXX("Hello there") → 0      0      OK         
countXX("Hexxo thxxe") → 2      2      OK         
countXX("") → 0      0      OK         
countXX("Kittens") → 0      0      OK         
countXX("Kittensxxx") → 2      2      OK

and with that you'd have to do "return count+1" if I am not mistaken?

If i return again count+1 i am getting wrong result
Avatar of gudii9

ASKER


http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#indexOf(int,%20int)

indexOf
public int indexOf(int ch,
          int fromIndex)
Returns the index within this string of the first occurrence of the specified character, starting the search at the specified index.
i think i looked at wrong indexOf API method where it is taking int ch and in fromIndex as variables not String and int as in our method
str.indexOf("xx", from)

where can i see above API method?
Please advise
Avatar of gudii9

ASKER

for(int from = 0; (from = str.indexOf("xx", from) + 1) > 0; count++);

instead of from name using 3 times can we use different names?
Avatar of gudii9

ASKER

looks like substring method is far easy to grasp than this index method to me

for(int from = 0; (from = str.indexOf("xx", from) + 1) > 0; count++);

when this loop ends. To me >0 is always satisfied leading to infinity loop. please advise
Avatar of gudii9

ASKER

package eePackage;

public class Test15 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int howMany= countXX("xxabcdxxxxxx");
		System.out.println("number is--->"+howMany);

	}
	
	static int countXX(String str) {
		int from = str.indexOf("xx") + 1;
        int count=0;
		while (from > 0)
		{
		   from = str.indexOf("xx", from) + 1;
		   System.out.println(from);
		   count++;
		}
		  return count;
		}

}

Open in new window


when i ran above code i got some confusing output different than yours

7
8
9
10
11
0
number is--->6

I have not got 1 at all.
Please advise
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of gudii9

ASKER

i finally found the api for this

int      lastIndexOf(String str, int fromIndex)
Returns the index within this string of the last occurrence of the specified substring, searching backward starting at the specified index.

str.indexOf("xx", from)

where can i find more simple examples on above api. please advise
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
(@all :

sorry, btw, in all this cuffuffle, I missed the fact that CPColin had incremented. viz:

int from = str.indexOf("xx") + 1;

Open in new window

)
instead of from name using 3 times can we use different names?
Yes, we could rewrite mccarl's solution to the following.
int countXX(String str) {
        int count = 0;
	int currentIndex = str.indexOf("xx");
        int fromIndex = 0;
        for( ; currentIndex >= 0; ){
               count++;
               fromIndex = currentIndex + 1;
	       currentIndex = str.indexOf("xx", fromIndex);
	}
        return count;   
}

Open in new window

As CPColin posted it is clearer as
int countXX(String str) {
        int count = 0;
	int currentIndex = str.indexOf("xx");
        int fromIndex = 0;
        while(currentIndex >= 0){
               count++;
               fromIndex = currentIndex + 1;
	       currentIndex = str.indexOf("xx", fromIndex);
	}
        return count;   
}

Open in new window

Avatar of gudii9

ASKER

for(int from = 0; (from = str.indexOf("xx", from) + 1) > 0; count++);
Above code using from for initialization termination(where 'from' used two times) and then count for increment

till now i am familiar only with for loops where initialization, termination and increment all deals with single variable say 'i' as below

class ForDemo {
    public static void main(String[] args){
         for(int i=1; i<11; i++){
              System.out.println("Count is: " + i);
         }
    }
}
/*package eePackage;

public class Test16 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}
	
	countXX("xxabcdxxxxxx");
	for(int from = 0; (from = str.indexOf("xx", from) + 1) > 0; count++){System.out.println(from);}

}*/

package eePackage;

public class Test16 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int howMany= countXX("axxabcdxxesxxaxx");
		System.out.println("number is--->"+howMany);

	}
	
	static int countXX(String str) {
		int count=0;
		for(int from = 0; (from = str.indexOf("xx", from) + 1) > 0; count++){
			System.out.println(from);
			//return count;
			}
		return count;
		
		
		}

}

Open in new window


when i tried above program i got correct  output including from position (which is 1 more of index position of xx)
2
8
12
15
number is--->4
We could rewrite mccarl's solution to the following.
int countXX(String str) {
        int count = 0;
	int currentIndex = str.indexOf("xx");
        int fromIndex = 0;
        for( ; currentIndex >= 0; ){
               count++;
               fromIndex = currentIndex + 1;
	       currentIndex = str.indexOf("xx", fromIndex);
	}
        return count;   
}

Open in new window

As CPColin posted it is clearer as
int countXX(String str) {
        int count = 0;
	int currentIndex = str.indexOf("xx");
        int fromIndex = 0;
        while(currentIndex >= 0){
               count++;
               fromIndex = currentIndex + 1;
	       currentIndex = str.indexOf("xx", fromIndex);
	}
        return count;   
}

Open in new window

Avatar of gudii9

ASKER

  for( ; currentIndex >= 0; ){
               count++;
               fromIndex = currentIndex + 1;

Open in new window


can we write for loop without initialization and increment.

what is the main difference between currentIndex and fromIndex.( how do i remove my focus on variable names but rather keep focus on what is happening and what is adding etc process, i get confused sometimes with variable names which are completely arbitrary right)
Please advise

I am wonder challenging nature of java where something like simple for loop can have so many ways of writing and still very thing is correct
can we write for loop without initialization and increment.
Yes. We could also write it as
int countXX(String str) {
        int count = 0;
	int currentIndex = str.indexOf("xx");
        int fromIndex = 0;
        for( ; ; ){
               if(currentIndex < 0)break;
               count++;
               fromIndex = currentIndex + 1;
	       currentIndex = str.indexOf("xx", fromIndex);
	}
        return count;   
}

Open in new window

what is the main difference between currentIndex and fromIndex
currentIndex is the index where we found the latest "xx" substring.  fromIndex is the index where we begin to look for the next "xx".
how do i remove my focus on variable names but rather keep focus on what is happening
I don't know. But, I think you are making good progress.
variable names which are completely arbitrary right
They are arbitrary. But, we should name them something that makes our code more readable.
I am wonder challenging nature of java
At some point, we fall in love with Java.
till now i am familiar only with for loops where initialization, termination and increment all deals with single variable say 'i' as below

Well if you are, then you are familiar with another language, not Java.
Avatar of gudii9

ASKER

I think you are making good progress.
that makes feel more confident. More more java i learn more more i feel i know only tiny bit and need to know whole lot. I feel i only drank glass full of water from ocean full of ocean :)
How to master java and  feel confident even if you face challenging situations. May be i wil put new topic of discussion for this.
How to master java and  feel confident even if you face challenging situations.

One way is to pay close attention to what people like mccarl have to say - because you won't most likely be able to find that level of knowledge around every corner, or from a text book. The point I am making is you have to understand the mechanics of what the top experts say, and not go off onto something else before you have understood each point.
Avatar of gudii9

ASKER

public class Test18 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int a=countXX("xxabcdxxxxxx");
		System.out.println("a is-->"+a);

	}
	static int countXX(String str) {
        int count = 0;
	int currentIndex = str.indexOf("xx");
        int fromIndex = 0;
        for( ; currentIndex >= 0; ){
               count++;
               fromIndex = currentIndex + 1;
	       currentIndex = str.indexOf("xx", fromIndex);
	       System.out.println("fromIndex is--->"+fromIndex);
	       System.out.println("currentIndex--->"+currentIndex);
	}
        return count;   
}
}

Open in new window


I merged different pieces from above comments to understand index(string, int) better. I got output as below

fromIndex is--->1
currentIndex--->6
fromIndex is--->7
currentIndex--->7
fromIndex is--->8
currentIndex--->8
fromIndex is--->9
currentIndex--->9
fromIndex is--->10
currentIndex--->10
fromIndex is--->11
currentIndex--->-1
a is-->6


I have not understood above output clearly. Please advise

I even looked below link to understand
http://www.tutorialspoint.com/java/lang/string_indexof_string_index.htm

But my challenge is still a challenge for me. please advise
Avatar of gudii9

ASKER

why it printed

fromIndex is--->1
currentIndex--->6
fromIndex is--->7
currentIndex--->7

1,6 then 7, 7?
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial