'How to tackle the Codingbat String-2 oneTwo challenge?

Here is the problem statement:

Given a string, compute a new string by moving the first char to come after the next two chars, so "abc" yields "bca". Repeat this process for each subsequent group of 3 chars, so "abcdef" yields "bcaefd". Ignore any group of fewer than 3 chars at the end.

Here is my code:

// oneTwo("abc") → "bca"
// oneTwo("tca") → "cat"
// oneTwo("tcagdo") → "catdog"  

public String oneTwo(String str) {
    String x = "";
    if (str.length() < 3) {
        return "";
        // return empty
    } else if (str.length() == 3) {
        String s = str.substring(1, str.length());
        x = s + str.substring(0, 1);      // last two + first char
    } else if (str.length() > 3) {
        int third = 2;
        // start with the third element index of 2
        for (int i = 0; i < str.length(); i++) {
            if (i == third) {
                // given three chars substring first char
                // substring last two chars and add that to x
                x += (str.substring(third - 1, third + 1) +
                        str.substring(third - 2, third - 2 + 1));
                third += 3;
                //work  with this line but why??????
            }
            //third +=3;
            // doesn't work with this line but why???????


        }// end of for loop
    }
    return x;
    // return modified string x
}

With third +=3 inside of if statement work but when I put that outside of if statement I don't get the desired output. I don't really understand why?



Solution 1:[1]

Hope this helps:

public String oneTwo(String str) {
    String str2 = "";
    for(int i=0; i<str.length()-2; i+=3) {
        str2 = str2+str.substring(i+1,i+3)+str.charAt(i);
    }
    return str2;
}

Solution 2:[2]

Because putting it outside the loop will cause third to be increased far too often. After the first iteration i is 0, third is 5, next iteration yields i=1, third=8; i=2, third=11; i=3, third=14, etc. -> i will never reach third.

I would improve your code by dropping the entire if-statement, remove third all together and simply increment by 3 in the for-loop:

for( int i = 2; i < str.length(); i+=3){
    x += (str.substring(third-1, third+1) + 
          str.substring(third-2, third-2 + 1));
}

If I am not misinterpreting your code you are missing logic for leaving the last characters alone if they are not part of group of three characters.

Solution 3:[3]

If you face such effects take a piece of paper and write down the values of the variables after each line of your code.


The if block creates an alternative execution path if the condition is true which is in every third loop iteration.

Anything behind the if block is executed in every loop iteration.

So when the line in question is inside the if block (before the closing brace) the value in variable third is only changed every third loop iteration.

When you move the line behind the closing brace the assignment is outside the if block and therefore executed every loop iteration.

Solution 4:[4]

For the comment = //work with this line but why??????

The value of "third" variable gets changed in the for loop only with i is equal to third character, otherwise the value of third will keep on increasing eg.

when i = 0, third = 2
when i = 1, third = 5
when i = 2, third = 8

so the if statement never gets triggered and hence it doesn't work. Hope this makes sense.

PS - I highly recommend using IDE debugger to understand this properly.
PS - It's better to use charAt method as compared for substring method for performance reason

Solution 5:[5]

public String oneTwo(String str) {
    String temp = "";
    String result = "";
    int i = 0;
    while (str.substring(i).length() >= 3) {
        temp = str.substring(i, i + 3);
        result += temp.substring(1) + temp.charAt(0);
        i += 3;
    }
    return result;
}

Solution 6:[6]

public String oneTwo(String str) {

 String str1 = "";
 if(str.length()<3){
  return str1; 
 }else if(str.length()>=3){
    for(int i =0; i<str.length()-2; i=i+3){
            str1 = str1 + str.substring(i+1,i+3)+ str.substring(i,i+1);

        }
 }

 return str1;
}

Solution 7:[7]

public String oneTwo(String str) {
  if(str.length()<3)return "";
  return str.substring(1,3)+str.substring(0,1)+oneTwo(str.substring(3));
}

this is fairly simple as a recursive problem

Solution 8:[8]

public String oneTwo(String str) {
        String newThreeChars = "";
        if(str.length()<3){
            return newThreeChars;
        }
        for(int i=0; i<str.length()/3; i+=3){
            String threeChars = str.substring(i,i+3);
            String redesigned = threeChars.substring(1) + threeChars.charAt(0);
            newThreeChars +=redesigned;
        }
        return newThreeChars;

    }

Solution 9:[9]

Another solution to look at...

public String oneTwo(String str) {
  int i = 0;
  String result = "";
  Character tmpChar = '\0';
  
  while(i <= str.length()-3){
    tmpChar = str.charAt(i);
    result = result + str.charAt(i+1) + str.charAt(i+2) + tmpChar;
    tmpChar = '\0';
    i = i + 3;
  }
  
  return result;
}

Solution 10:[10]

First, We loop through each letter of the given String just stopping shy of the last two letters because the word we are looking for is three letters long. Then, we are returning true if there is two letter "b"'s exactly one character apart.

public boolean bobThere(String str) {
  for (int i = 0; i < str.length() - 2; i++) {
    if (str.charAt(i) == 'b' && str.charAt(i+2) == 'b')
    return true;
  }
  return false;
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 VincenzoC
Solution 2 luk2302
Solution 3 Timothy Truckle
Solution 4
Solution 5 Alex85
Solution 6 Soumya Rao
Solution 7 Ryan
Solution 8 Anar Agayev
Solution 9 Maitri Vaghela
Solution 10 Choych