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

asked on

string yak challenge

Hi,

I am trying below challenge
http://codingbat.com/prob/p126212

i have not understood the problem description. Please advise on how to proceed
Suppose the string "yak" is unlucky. Given a string, return a version where all the "yak" are removed, but the "a" can be any char. The "yak" strings will not overlap.

stringYak("yakpak") → "pak"
stringYak("pakyak") → "pak"
stringYak("yak123ya") → "123ya"
Avatar of ozo
ozo
Flag of United States of America image

It looks like the tests on that challenge do not make use of the
 but the "a" can be any char
clause, so I'd suggest attempting the problem ignoring that part.
SOLUTION
Avatar of dpearson
dpearson

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
public String stringYak(String str) {
  return str.replace(str.substring(str.indexOf("y"),str.indexOf("k",str.indexOf("y"))+1),"");
}

Open in new window

Avatar of gudii9

ASKER

public String stringYak(String str) {
  StringBuilder result = new StringBuilder() ;
  int i = 0 ;
  int len = str.length() ;
  
  while (i < len) {
      if (i+2 < len && str.charAt(i) == 'y' && str.charAt(i+2) == 'k') {
          // We've found a yak string
          result.append(str.substring(i+3,len));
      } else {
          // This is not part of yak string so we should keep it
      }
      i++ ;
  }
  return result.toString() ;
}

Open in new window


i wrote as above some test cases passed but some are failed as below.

Expected      Run            
stringYak("yakpak") → "pak"      "pak"      OK         
stringYak("pakyak") → "pak"      ""      X         
stringYak("yak123ya") → "123ya"      "123ya"      OK         
stringYak("yak") → ""      ""      OK         
stringYak("yakxxxyak") → "xxx"      "xxxyak"      X         
stringYak("HiyakHi") → "HiHi"      "Hi"      X         
stringYak("xxxyakyyyakzzz") → "xxxyyzzz"      "yyyakzzzzzz"      X         


please advise
What happens when
This is not part of yak string so we should keep it
?
What happens when there is more than one "yak" in the string?
Avatar of gudii9

ASKER

public String stringYak(String str) {
  StringBuilder result = new StringBuilder() ;
  int i = 0 ;
  int len = str.length() ;
  
  while (i <= len) {
  
      if (i+2 < len && str.charAt(i) == 'y' && str.charAt(i+2) == 'k') {
          // We've found a yak string
          result.append(str.substring(len-3));
      } else {
          // This is not part of yak string so we should keep it
      }
      i++ ;
  }
  return result.toString() ;
}

Open in new window


I modified like above and still faling lot of test cases
Expected	Run		
stringYak("yakpak") → "pak"	"pak"	OK	    
stringYak("pakyak") → "pak"	"yak"	X	    
stringYak("yak123ya") → "123ya"	"3ya"	X	    
stringYak("yak") → ""	"yak"	X	    
stringYak("yakxxxyak") → "xxx"	"yakyak"	X	    
stringYak("HiyakHi") → "HiHi"	"kHi"	X	    
stringYak("xxxyakyyyakzzz") → "xxxyyzzz"	"zzzzzz"	X	 

Open in new window


please advise
Avatar of dpearson
dpearson

Your code is trying to keep the pieces that match 'yak'.  You're meant to be skipping those.

Try this instead:

public String stringYak(String str) {
  StringBuilder result = new StringBuilder() ;
  int i = 0 ;
  int len = str.length() ;
  
  while (i < len) {
  
      if (i+2 < len && str.charAt(i) == 'y' && str.charAt(i+2) == 'k') {
          // We've found a yak string
          i += 2 ;
      } else {
          // This is not part of yak string so we should keep it
          result.append(str.charAt(i)) ;
      }
      i++ ;
  }
  return result.toString() ;
}

Open in new window

Avatar of gudii9

ASKER

public String stringYak(String str) {
  StringBuilder result = new StringBuilder() ;
  int i = 0 ;
  int len = str.length() ;
  
  while (i <= len) {
  
      if (i+2 < len && str.charAt(i) == 'y' && str.charAt(i+2) == 'k') {
          // We've found a yak string
        //  result.append(str.substring(len-3));
          //public StringBuilder delete(int start, int end)
          //result.delete(0,i);
          result.delete(i,len-1);
      } else {
          // This is not part of yak string so we should keep it
      }
      i++ ;
  }
  return result.toString() ;
}

Open in new window


I tried to delete as above getting failures in test cases and also getting string index out of bound. please advise
Expected	Run		
stringYak("yakpak") → "pak"	""	X	    
stringYak("pakyak") → "pak"	"Exception:java.lang.StringIndexOutOfBoundsException (line number:13)"	X	    
stringYak("yak123ya") → "123ya"	""	X	    
stringYak("yak") → ""	""	OK	    
stringYak("yakxxxyak") → "xxx"	"Exception:java.lang.StringIndexOutOfBoundsException (line number:13)"	X	    
stringYak("HiyakHi") → "HiHi"	"Exception:java.lang.StringIndexOutOfBoundsException (line number:13)"	X	    
stringYak("xxxyakyyyakzzz") → "xxxyyzzz"	"Exception:java.lang.StringIndexOutOfBoundsException (line number:13)"	X	   

Open in new window

Avatar of gudii9

ASKER

How to write using for loop rather than while loop. I like for loop better some reason. Also i like to use string builder delete method rather than append method in this case. How to make sure i never get string index out of bound exceptions in future. please advise
Getting StringIndexOutOfBoundsException is indicative of the fact that you still do not understand the workings of the for loop, and how it relies on its index incrementation.

As to writing for loops instead of whiles, this is not a choice you should make based on personal preference, but on programming reasoning. Unless you'd like to explain how that works here.
Avatar of gudii9

ASKER

public String stringYak(String str) {
  StringBuilder result = new StringBuilder() ;
  int i = 0 ;
  int len = str.length() ;
  
  while (i <= len) {
  
      if (i+2 < len && str.charAt(i) == 'y' && str.charAt(i+2) == 'k') {
        
          result.delete(i,len-1);
      } else {
         
      }
      i++ ;
  }
  return result.toString() ;
}

Open in new window


i see reason for string index out of bound is i am trying to delte on result string builder which has nothing in it.

I wonder how i pass one test case as below
Expected	Run		
stringYak("yakpak") → "pak"	""	X	    
stringYak("pakyak") → "pak"	"Exception:java.lang.StringIndexOutOfBoundsException (line number:10)"	X	    
stringYak("yak123ya") → "123ya"	""	X	    
stringYak("yak") → ""	""	OK	    
stringYak("yakxxxyak") → "xxx"	"Exception:java.lang.StringIndexOutOfBoundsException (line number:10)"	X	    
stringYak("HiyakHi") → "HiHi"	"Exception:java.lang.StringIndexOutOfBoundsException (line number:10)"	X	    
stringYak("xxxyakyyyakzzz") → "xxxyyzzz"	"Exception:java.lang.StringIndexOutOfBoundsException (line number:10)"

Open in new window

Avatar of gudii9

ASKER

public String stringYak(String str) {
  StringBuilder result = new StringBuilder() ;
  int i = 0 ;
  int len = str.length() ;
  
  while (i < len) {
  
      if (i+2 < len && str.charAt(i) == 'y' && str.charAt(i+2) == 'k') {
          // We've found a yak string
       [b]   i += 2 ;[/b]
      } else {
          // This is not part of yak string so we should keep it
          result.append(str.charAt(i)) ;
      }
   [b]   i++ ;[/b]
  }
  return result.toString() ;
}

Open in new window


in above code as bolded why we are incrementing by 2(not 3) in the if loop and then incrementing by 1 (not 3 here )next to else loop. Doe the i value increamented in if loop carry over to i++ line(which is next to else loop?)
Avatar of gudii9

ASKER

package eePackage;

public class Test30 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String str2=stringYak("pakyak123ya");
		System.out.println("str2 value is--->"+str2);

	}

	public static String stringYak(String str) {
		  StringBuilder result = new StringBuilder() ;
		  int i = 0 ;
		  int len = str.length() ;
		  
		  while (i < len) {
		  
		      if (i+2 < len && str.charAt(i) == 'y' && str.charAt(i+2) == 'k') {
		          // We've found a yak string
		        i += 2 ;
		      } else {
		          // This is not part of yak string so we should keep it
		          result.append(str.charAt(i)) ;
		      }
		      i++ ;
		  }
		  return result.toString() ;
		}

}

Open in new window


i see i jumped to 5 after i=3 after else loop once entering to if loop as attached.
so i is method local varialbe common across whole method right similar to global across common across whole class?
yakChallenge.jpg
You have code there that satisfies the challenge - it works.

So you are done!

Not quite sure what you mean about 'i' - it's in scope throughout the method call.
in above code as bolded why we are incrementing by 2(not 3) in the if loop and then incrementing by 1 (not 3 here )next to else loop. Does the i value increamented in if loop carry over to i++ line(which is next to else loop?)

Every pass through the loop ends up executing the i++ line - so we always move at least 1 character forward.

So when we find the 'y*k' pattern, we only need to move 2 additional characters forward, so that in total (2+1) we'll end up 3 characters ahead next time through the loop.

So yes this is true:
 
the i value incremented in if loop carry over to i++ line

Doug
Avatar of gudii9

ASKER

return str.replace(str.substring(str.indexOf("y"),str.indexOf("k",str.indexOf("y"))+1),"");

Open in new window

in the above code

substring takes 2 integers right one start and other end(excluding last)

str.substring(str.indexOf("y"),str.indexOf("k",str.indexOf("y")

what is above code doing.

i understand whatever is coming is replaced by ""
please advise
substring takes 2 integers right one start and other end(excluding last)

That's right.

So >>str.substring(str.indexOf("y"),str.indexOf("k",str.indexOf("y")<<

it starts at the index of "y", and extends FROM THERE PLUS 1 to look for "k", and replace it with nothing.
Avatar of gudii9

ASKER

what is integer and what is integer 2 here inside the substring method. Please advise
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
Avatar of gudii9

ASKER

import java.io.*;

public class Test {

   public static void main(String args[]) {
     // String Str = new String("Welccomeeeeo to Tutorialspoint.com");
	  String Str = new String("Wa1b2bcaaaaerwfafafa");
      String SubStr1 = new String("Tutorials");
      String SubStr2 = new String("Sutorials");
      System.out.println("length is"+Str.length());

      System.out.print("Found Index 1--:" );
      System.out.println(Str.indexOf( 'o' ));
      System.out.print("Found Index 2--:" );
      System.out.println(Str.indexOf( 'a', 19));
      System.out.print("Found Index 3---:" );
      System.out.println( Str.indexOf( SubStr1 ));
      System.out.print("Found Index 4---:" );
      System.out.println( Str.indexOf( SubStr1, 15 ));
      System.out.print("Found Index 5---:" );
      System.out.println(Str.indexOf( SubStr2 ));
   }
}

Open in new window


i ran above and got below output
length is20
Found Index 1--:-1
Found Index 2--:19
Found Index 3---:-1
Found Index 4---:-1
Found Index 5---:-1
it make perfect sense why i got 19

but indexOf within other indexOf is confusing to me as below
str.indexOf("k",str.indexOf("y"))+1
I am trying to understand what you mean by
extends FROM THERE PLUS 1 to look for "k",
why we have to do plus 1 why we have to extend from there....please advise
Is there is a way to break this program in simple steps and make it independent of index of y if at all possible.
please advise
str.indexOf("k",str.indexOf("y"))+1

this means " tell us the index of "k", but start looking for it from where you found "y".  When that index is obtained, add 1 to it.

After the 1 has been added, give us that finished index number so we can use it as the second parameter for the substring method - (to determine where the search extent ends in the string).
Avatar of gudii9

ASKER

When that index is obtained, add 1 to it.

This is because we exclude the end index within substring method right
substring(start, end)
where exclude end index
This is because we exclude the end index within substring method right
We don't EXCLUDE the end index. It's used as the end-of-substring marker.

The second argument of substring - (IF two arguments are supplied) - is  exclusive.
Avatar of gudii9

ASKER

The second argument of substring - (IF two arguments are supplied) - is  exclusive.

I thought we are sending two int arguments to this method. Am i wrong in saying that

str.substring(str.indexOf("y"),str.indexOf("k",str.indexOf("y"))+1)
Avatar of gudii9

ASKER

str.substring(str.indexOf("y"),str.indexOf("k",str.indexOf("y"))+1)

Open in new window

i felt writing like below is better (second int argument within parenthesis )

str.substring(str.indexOf("y"),(str.indexOf("k",str.indexOf("y"))+1) )

am i right?
please advise
Well ok, but you'd have to do this:

 return str.replace(str.substring(str.indexOf("y"),(str.indexOf("k",str.indexOf("y"))+1)),"");

Open in new window

I thought we are sending two int arguments to this method. Am i wrong in saying that

If you mean the substring method, then yes, it is taking 2 arguments.

I was simply pointing out that the API provides two forms of arguments for this method - it can either be called with 1 argument, or with 2. This time we need both. Under OTHER circumstances, just one might be sufficient. Say you want a substring of Hamburger. "Hamburger".substring(3) will give you "burger".
Try to run these examples which show you how substring works :

System.out.println("Hamburger".substring(3));
System.out.println("Hamburger".substring(3,4));
System.out.println("Hamburger".substring(3,7));
System.out.println("Hamburger".substring(3,"Hamburger".indexOf("e","Hamburger".indexOf("b")+1)));

Open in new window


. . .  before you run them, can you tell us what you think each will print out?
This is another one you can analyse :

System.out.println("Give me "+"Hamburger".substring(1,2)+" "+"Hamburger".substring("Hamburger".indexOf("b","Hamburger".indexOf("a")+1),"Hamburger".length()));

Open in new window

Avatar of gudii9

ASKER

System.out.println("Hamburger".substring(3));----burger
System.out.println("Hamburger".substring(3,4));---b
System.out.println("Hamburger".substring(3,7));--burg
System.out.println("Hamburger".substring(3,"Hamburger".indexOf("e","Hamburger".indexOf("b")+1)));---this i do not know


i think i got solid understanding of substring but my mind going blank with indexOf aling with substrng
Avatar of gudii9

ASKER

System.out.println("Hamburger".substring(3,"Hamburger".indexOf("e","Hamburger".indexOf("b")+1)));---this i do not know

"Hamburger".substring(3,x)
where x is "Hamburger".indexOf("e","Hamburger".indexOf("b")+1)
Avatar of gudii9

ASKER

"Hamburger".indexOf("e","Hamburger".indexOf("b")+1)

i supposed to look for index of b after finding first occurence of e right
so after
Hamburger so it is -1

or may be other way

i supposed to look for index of e after finding first occurence of b right
Hamburger so it is 6

If i consider as 6  then

System.out.println("Hamburger".substring(3,"Hamburger".indexOf("e","Hamburger".indexOf("b")+1)));
System.out.println("Hamburger".substring(3,6));---this is  bur
Avatar of gudii9

ASKER

That's right.

So >>str.substring(str.indexOf("y"),str.indexOf("k",str.indexOf("y")<<

it starts at the index of "y", and extends FROM THERE PLUS 1 to look for "k", and replace it with nothing.

it has 3 indexOf() which consuses me.

can we break it down to simple steps
Step 1 = str.indexOf("y")
Step 2 = str.indexOf("k",str.indexOf("y")) =  str.indexOf("k",Step 1)
Step 3 = str.substring(str.indexOf("y"),str.indexOf("k",str.indexOf("y")) = str.substring(Step 1,Step 2)
Avatar of gudii9

ASKER

Step 2 = str.indexOf("k",str.indexOf("y")) =  str.indexOf("k",Step 1)
says find index of k after finding y?(i am still not completely clear on step2 )

cannot we do step 2 like step 1 instead of making step 2 dependent on step 1

Step 2 = str.indexOf("k")

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