0

So, I was solving this problem on CodingBat

Given a string, compute recursively (no loops) a new string where all appearances of "pi" have been replaced by "3.14".

changePi("xpix") → "x3.14x"

changePi("pipi") → "3.143.14"

changePi("pip") → "3.14p"

Here is my code:

public String changePi(String str) {
    if (str.length() < 2)
        return str;
    char c1 = str.charAt(0);
    char c2 = str.charAt(1);
    if (c1 == 'p' && c2 == 'i')
        return "3.14" + changePi(str.substring(2));
    return c1 + c2 + changePi(str.substring(2));
}

This code is not working for many test cases as shown in the image below enter image description here

I'm unable to understand what is wrong with my recursive code and why it is showing such output. Can anyone please help me in understanding what I did wrong?

Community
  • 1
  • 1
KhiladiBhaiyya
  • 633
  • 1
  • 14
  • 43
  • 3
    Hint: In java, `'a' + 'b' + "c"` is not `"abc"`. Order of operations is what is killing your code – smac89 Sep 16 '19 at 17:04
  • 1
    Possible duplicate of [Java add chars to a string](https://stackoverflow.com/questions/1654546/java-add-chars-to-a-string) – Tom Sep 16 '19 at 17:06
  • You can also check [Why is my char printing as a number instead of a character?](//stackoverflow.com/q/30763489) and [Java += operator on String with charAt() methods results in char addition](//stackoverflow.com/a/24938675) – Tom Sep 16 '19 at 17:07
  • The underlying issue is not because of string concatenation. I posted a fix below along with an explanation and correct output. – Kaan Sep 16 '19 at 18:32
  • @kaan It may not have been the main issue, but it was causing the outputs to look *extra* wonky, and your fix did secretly handle it. – arcadeblast77 Sep 16 '19 at 19:53
  • @DG4 Your solution is checking these indexes: `{0, 1}, {2, 3}, {4, 5}, ...` But you really want to check these ones: `{0, 1}, {1, 2}, {2, 3}, ...` – arcadeblast77 Sep 16 '19 at 19:59

3 Answers3

2

Your solution needs a small tweak – when you've found a p and i together, you are correctly skipping ahead 2 characters to look at the remainder of the string – you're doing that with return "3.14" + changePi(str.substring(2));.

However, when you do not find a p and i together, you need to change your logic to skip ahead just one character instead of two. So instead of this:

return c1 + c2+ changePi(str.substring(2));

do this:

return c1 + changePi(str.substring(1));

After making that change, I get the following output (using each of your inputs) which matches your expected outputs:

x3.14x
3.143.14
3.14p
3.14
hip
p
x

3.14xx
xyzzy
Kaan
  • 5,434
  • 3
  • 19
  • 41
1

Here are a couple alternatives to the problem. The second one is similar to your approach. In the first one, I had originally included a target substitution text so I would need to determine its length. Hence the "pi".length() use as I decided to leave it in.


       public static void main(String[] args) {
          String[] tests = {
                "piabcpiefgpi", "xxxxxxpix", "xpix", "pip", "3.14", "3.14p",
                "hip", "p", "x", "", "pixx", "xyzzy"
          };
          for (String t : tests) {
             System.out.println(t + " --> " + replaceV2(t));
          }
       }

       public static String replaceV1(String a) {
          int i = a.indexOf("pi");
          if (i < 0) {
             return a;
          }
          return replaceV1(
                a.substring(0, i) + "3.14" + a.substring(i + "pi".length()));
       }

       public static String replaceV2(String a) {
          if (a.length() < 2) {
             return a;
          }

          if (a.startsWith("pi")) {
             a = "3.14" + replaceV2(a.substring(2));
          }
          return a.substring(0, 1) + replaceV2(a.substring(1));
       }
    }

They both print the following.

piabcpiefgpi --> 3.14abc3.14efg3.14
xxxxxxpix --> xxxxxx3.14x
xpix --> x3.14x
pip --> 3.14p
3.14 --> 3.14
3.14p --> 3.14p
hip --> hip
p --> p
x --> x
 --> 
pixx --> 3.14xx
xyzzy --> xyzzy
WJS
  • 36,363
  • 4
  • 24
  • 39
0
'''  change pi to 3.14 python code'''

def changePi(s):
    if len(s) == 2 and s == 'pi' :  return '3.14'
    if len(s) <= 2 :  return s 
    chars , sub = s[0:2] , s[1:]
    if chars == 'pi':
       chars = '3.14'
       sub = sub[1:]
    else:  chars =  chars[0]
    return chars + changePi(sub) 

print changePi("xpix") 
print changePi("pipi") 
print changePi("pip")