We help IT Professionals succeed at work.

plusOut java challenge

548 Views
Last Modified: 2016-04-08
Hi,
I am working on below challenge
http://codingbat.com/prob/p170829
I tried my code as below
public String plusOut(String str, String word) {
return str.replaceAll(".word.","+word+");
  
}

Open in new window

I am getting below result
Expected      Run            
plusOut("12xy34", "xy") → "++xy++"      "12xy34"      X         
plusOut("12xy34", "1") → "1+++++"      "12xy34"      X         
plusOut("12xy34xyabcxy", "xy") → "++xy++xy+++xy"      "12xy34xyabcxy"      X         
plusOut("abXYabcXYZ", "ab") → "ab++ab++++"      "abXYabcXYZ"      X         
plusOut("abXYabcXYZ", "abc") → "++++abc+++"      "abXYabcXYZ"      X         
plusOut("abXYabcXYZ", "XY") → "++XY+++XY+"      "abXYabcXYZ"      X         
plusOut("abXYxyzXYZ", "XYZ") → "+++++++XYZ"      "abXYxyzXYZ"      X         
plusOut("--++ab", "++") → "++++++"      "--++ab"      X         
plusOut("aaxxxxbb", "xx") → "++xxxx++"      "aaxxxxbb"      X         
plusOut("123123", "3") → "++3++3"      "123123"      X         
other tests

how to  improve my approach, results and design of this challenge. How do i make a graphical venn or flow chart or some other relevant diagram to design it before writing code to decide best strategy?
 Please advise
Comment
Watch Question

CERTIFIED EXPERT
Most Valuable Expert 2014
Top Expert 2015
Commented:
This one is on us!
(Get your first solution completely free - no credit card required)
UNLOCK SOLUTION
Dan CraciunIT Consultant
CERTIFIED EXPERT
Commented:
This one is on us!
(Get your first solution completely free - no credit card required)
UNLOCK SOLUTION
awking00Information Technology Specialist
CERTIFIED EXPERT
Commented:
This one is on us!
(Get your first solution completely free - no credit card required)
UNLOCK SOLUTION
CERTIFIED EXPERT
Top Expert 2016
Commented:
This one is on us!
(Get your first solution completely free - no credit card required)
UNLOCK SOLUTION
Dan CraciunIT Consultant
CERTIFIED EXPERT

Commented:
@CEHJ: very nice. Short and easy to understand.

Basically you avoided the problem "you cannot negate a whole word in regex" by using NUL instead of the search string.
ozo
CERTIFIED EXPERT
Most Valuable Expert 2014
Top Expert 2015

Commented:
public String plusOut(String str, String word) {
  word="(\\Q"+word.replaceAll("\\+","\\E.\\Q")+"\\E)";
  return str.replaceAll(word+"|.", "+$1").replaceAll("\\+"+word,"$1");
}
CERTIFIED EXPERT

Commented:
Does anyone have an explanation for the result produced by this:

for (int y=0;y<str.length();y++){
      
      if(!(str.indexOf(word,y)==y)){
         str=str.replace(str.charAt(y),'+'); 
      }
      else{y+= (word.length()-1);}
              
  }
  return str;

Open in new window

ozo
CERTIFIED EXPERT
Most Valuable Expert 2014
Top Expert 2015

Commented:
str.replace(str.charAt(y),'+'); may replace more than one character
CERTIFIED EXPERT

Commented:
Ah yes - I always forget about that behaviour of the method for some reason. My bad, thanks.
CERTIFIED EXPERT
Top Expert 2016

Commented:
You can get the effect you wanted (with actually more efficiency) by doing this sort of thing:
    public String plusOut(String str, String word) {
        StringBuilder sb = new StringBuilder(str);
        int y = 0;

        while (y < sb.length()) {
            if (!(sb.indexOf(word, y) == y)) {
                sb.setCharAt(y, '+');
                y++;
            } else {
                y += word.length();
            }
        }

        return sb.toString();
    }

Open in new window

CERTIFIED EXPERT

Commented:
O gosh, yes, thanks CEHJ - I should have gone that route.

Think I've gone bats under the sheer weight of challenges.

 ;)
CERTIFIED EXPERT
Top Expert 2016

Commented:
Moving the call to length() at line 10 and replacing it with a variable would of course be better
CERTIFIED EXPERT

Commented:
I was (incorrectly) mutating String, but, in any event, what I was aiming at was:

public String plusOut(String str, String word) {
  
  for ( int y=0;y<str.length();y++){
      
      if(!(str.indexOf(word,y)==y)){
	  
		 char[] ch = str.toCharArray();
		 ch[y]='+';
		 str = new String(ch); 
      }
      else{y+= (word.length()-1);}
    
  }
  return str;
}

Open in new window


(which I can only defend in a sense by the fact that being iterative rather than esoterically RE etc., may be more digestible for the OP) ;)
CERTIFIED EXPERT
Top Expert 2016

Commented:
Again, you wouldn't call toCharArray() in a loop
CERTIFIED EXPERT

Commented:
Can I ask you for more detail / background on that pls?
CERTIFIED EXPERT
Top Expert 2016

Commented:
Well it's just a case of efficiency and not creating unnecessary allocations. Your code is creating a str.length() number of String instances, plus a str.length() number of char[] (toCharArray does not return the actual array that backs the String, it creates a copy)
CERTIFIED EXPERT

Commented:
Right. Important then, particularly if dealing with a larger number of Strings I guess. Would it make a lot of impact at this scale?
CERTIFIED EXPERT
Top Expert 2016

Commented:
No ;)
CERTIFIED EXPERT

Commented:
Thanks. Edifying and concise. ;)

(And seeing as the Q is marked 'abandoned', guess one may as well put the bandwidth to 'best use')

;)

Author

Commented:
public class PlusOutEx {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println("value is"+plusOut("12xy34", "xy")); //→ "++xy++"

	}
	
	public static String plusOut(String str, String word) {
		int x=str.indexOf(word);
		System.out.println("x is--->"+x);
		System.out.println("--->"+str.substring(x,x+2));
		return str.replaceAll(str.substring(x,x+2),"++");
		  
		}

}

Open in new window

i wrote as above but that needs to be refined to get opposite effect

Author

Commented:
can i tweak my above approach to pass all tests?

Author

Commented:
please advise

Author

Commented:
trying to see easiest approach
ozo
CERTIFIED EXPERT
Most Valuable Expert 2014
Top Expert 2015

Commented:
public String plusOut(String str, String word) {
  String out="";
  String w="";
  for( String p:str.split("\\Q"+word,-1) ){
     out += w;
     out += p.replaceAll(".","+");
     w = word;
  }
  return out;
}

Open in new window

Author

Commented:
 for( String p:str.split("\\Q"+word,-1) ){

what is meaning of above line?

\\Q means what?
please advise

Author

Commented:
     if (!(str.indexOf(str.charAt(i)) == idx)) {

what is meaning of above line in below solution

so idx is 2 which makes sense .

so we are checking 2 is equal to charAt(0) and then indexOf not equal?
public class PlusOutEx {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println("value is"+plusOut("12xy34", "xy")); //→ "++xy++"

	}
	
	public static String plusOut(String str, String word) {
		StringBuilder sb = new StringBuilder();
		int len = word.length();
		for (int i = 0; i < str.length(); i++) {
			int idx = str.indexOf(word);
			if (!(str.indexOf(str.charAt(i)) == idx)) {
				sb.append("+");
			} else {
			sb.append(word);
			i+= (len - 1);
			}
		}
	        return sb.toString();
	}

}

Open in new window

Author

Commented:
charAt 0 is 1
so str.indexOf 1 is 0 which on comparing with idx 2
0==2 is false
so there is ! so false becomes true as
!false is true
then we are appening + to sb as below

sb.append("+");


else why are we doing as below ie appending word to sb

else {
                  sb.append(word);

Author

Commented:
as attached i see we are doing + for all other characters apart from word and appending word for else condition

why are we doing below assignment or addition

i+= (len - 1);
falseValue.png

Author

Commented:
public String plusOut(String str, String word) {
	for (int y=0;y<str.length();y++){
      
      if(!(str.indexOf(word,y)==y)){
         str=str.replace(str.charAt(y),'+'); 
      }
      else{y+= (word.length()-1);}
              
  }
  return str;

}

Open in new window


above failing below two test cases. How to fix those two failing test cases
Expected      Run            
plusOut("12xy34", "xy") → "++xy++"      "++xy++"      OK         
plusOut("12xy34", "1") → "1+++++"      "1+++++"      OK         
plusOut("12xy34xyabcxy", "xy") → "++xy++xy+++xy"      "++xy++xy+++xy"      OK         
plusOut("abXYabcXYZ", "ab") → "ab++ab++++"      "ab++ab++++"      OK         
plusOut("abXYabcXYZ", "abc") → "++++abc+++"      "++++++++++"      X         
plusOut("abXYabcXYZ", "XY") → "++XY+++XY+"      "++XY+++XY+"      OK         
plusOut("abXYxyzXYZ", "XYZ") → "+++++++XYZ"      "++++++++++"      X         
plusOut("--++ab", "++") → "++++++"      "++++++"      OK         
plusOut("aaxxxxbb", "xx") → "++xxxx++"      "++xxxx++"      OK         
plusOut("123123", "3") → "++3++3"      "++3++3"      OK         
other tests
OK      

Author

Commented:
if(!(str.indexOf(word,y)==y)){

what is meaning of above line. Please advise
http://www.tutorialspoint.com/java/java_string_indexof.htm

so we are checking indexOf xy starting at y index is same as y which is 0 for first iteration?
falseValue2.png

Author

Commented:
so after y=2 we are jumping to y=4 as attached to skip xy right?
falseValue3.png
ozo
CERTIFIED EXPERT
Most Valuable Expert 2014
Top Expert 2015

Commented:
str.replace(str.charAt(y),'+'); may replace more than one character

Author

Commented:
str.replace(str.charAt(y),'+'); may replace more than one character

so due to above reason it is failing those two tests?
how to fix below solution then.
public String plusOut(String str, String word) {
	for (int y=0;y<str.length();y++){
      
      if(!(str.indexOf(word,y)==y)){
         str=str.replace(str.charAt(y),'+'); 
      }
      else{y+= (word.length()-1);}
              
  }
  return str;

}

Open in new window


please advise
ozo
CERTIFIED EXPERT
Most Valuable Expert 2014
Top Expert 2015

Commented:
public String plusOut(String str, String word) {
  for (int y=0;y<str.length();y++){
      
      if(!(str.indexOf(word,y)==y)){
         str=str.replaceFirst("\\Q"+str.charAt(y),"+"); 
      }
      else{y+= (word.length()-1);}
              
  }
  return str;
}

Open in new window

But that would still fail if one of the tests was plusOut("xyx", "xy")
ozo
CERTIFIED EXPERT
Most Valuable Expert 2014
Top Expert 2015

Commented:
public String plusOut(String str, String word) {
  for (int y=0;y<str.length();y++){
      
      if(!(str.indexOf(word,y)==y)){
         str=str.replaceFirst("(.{"+y+"}).","$1+"); 
      }
      else{y+= (word.length()-1);}
              
  }
  return str;
}

Open in new window

Author

Commented:
public String plusOut(String str, String word) {
  for (int y=0;y<str.length();y++){
      
      if(!(str.indexOf(word,y)==y)){
         str=str.replaceFirst("(.{"+y+"}).","$1+"); 
      }
      else{y+= (word.length()-1);}
              
  }
  return str;
}

Open in new window


above passed all tests

Author

Commented:
what is meaning of below 3 lines . please advise

 
      if(!(str.indexOf(word,y)==y)){
         str=str.replaceFirst("(.{"+y+"}).","$1+");
     
      else{y+= (word.length()-1);}

Author

Commented:
not sure why code comments and quotes are missing in experts exchange now.

Any way i like below solution after debugging more after refrreing indexOf, replace, charAt functions as below
http://www.tutorialspoint.com/java/java_string_replace.htm
http://www.tutorialspoint.com/java/java_string_charat.htm
http://www.tutorialspoint.com/java/java_string_indexof.htm


public class PlusOutEx {

      /**
       * @param args
       */
      public static void main(String[] args) {
            // TODO Auto-generated method stub
            System.out.println("value is" + plusOut("12xy34", "xy")); // → "++xy++"

      }

      public static String plusOut(String str, String word) {
            for (int y = 0; y < str.length(); y++) {

                  if (!(str.indexOf(word, y) == y)) {
                        str = str.replace(str.charAt(y), '+');
                  } else {
                        y += (word.length() - 1);
                        System.out.println("hi");
                  }

            }
            return str;

      }

}


But how you remember all above methods and what arguments they take on top of the head all the time?

so we are basically checking if 1st occurence of word does nto match the y position we are safely making that character as +
else we are jumping to position of end of that word occurence within str.

But i wonder why this approach is not good has more allocations etc ? Not clear why it created too many strings etc. How many strings it creates in total?



Well it's just a case of efficiency and not creating unnecessary allocations. Your code is creating a str.length() number of String instances, plus a str.length() number of char[] (toCharArray does not return the actual array that backs the String, it creates a copy)




public String plusOut(String str, String word) {
 
  for ( int y=0;y<str.length();y++){
     
      if(!(str.indexOf(word,y)==y)){
        
             char[] ch = str.toCharArray();
             ch[y]='+';
             str = new String(ch);
      }
      else{y+= (word.length()-1);}
   
  }
  return str;
}

Author

Commented:
i forgot attachment
debugMore.png
ozo
CERTIFIED EXPERT
Most Valuable Expert 2014
Top Expert 2015

Commented:
how you remember all above method
I don't.
I look them up on publicly accessible on-line documentation.
And when I'm not sure where the documentation is, I use a search engine.
Unlock the solution to this question.
Join our community and discover your potential

Experts Exchange is the only place where you can interact directly with leading experts in the technology field. Become a member today and access the collective knowledge of thousands of technology experts.

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.