'Why is my code for Codingbat String-2 EndOther not working?

I won't lie, this is sort of homework for my AP Computer Science class. But I talked to my teacher, and he couldn't figure it out either.

So I'm doing the Java CodingBat problem String-2 endOther here, and I don't know why my code isn't working properly.

The goal of the challenge is to determine if one string appears at the very end of the other string. If so, return true, otherwise return false.

Example: If the strings were "Hiabc" and "abc", it would return true, but "Hiabcx" and "bc" would return false because "bc" isn't at the end. Note: Case does not matter.

My code works for all of the examples that it runs through, except for "other tests". I might have been able to figure out how to fix it, except I don't know what "other tests" it ran. So any help on this? Here's my code:

public boolean endOther(String a, String b) {
    a = a.toLowerCase();
    b = b.toLowerCase();
    if (a.contains(b) && a.indexOf(b) == a.length() - b.length()) {
        return true;
    } else if (b.contains(a) && b.indexOf(a) == b.length() - a.length()) {
        return true;
    } else {
        return false; 
    }
}

Thanks!



Solution 1:[1]

I know that an answer to this question has already been posted, but as far as your original code goes, I think I have an idea of what went wrong. If the one of the "other tests" used a string such as "abc" and was compared with a string that had more than one occurrence of "abc" such as "Hiabcabc", then your code would fail even though "abc" is at the end of "Hiabcabc". The reason this happens is that indexOf() looks for the first occurrence of the parameter and returns the index of it. This would result in false negatives in tests that contained more than one occurrence of the smaller string.

Using substring() is probably the best solution to this problem as it would allow you to look specifically at the end of the string, however if you wanted to modify your code as little as possible, you could use lastIndexOf() as an alternative to indexOf(). This would result in your code passing all of the tests.

Here's your modified code:

public boolean endOther(String a, String b) {
  a = a.toLowerCase();
  b = b.toLowerCase();
  if (a.contains(b) && a.lastIndexOf(b) == a.length() - b.length()) {
    return true;
  } else if (b.contains(a) && b.lastIndexOf(a) == b.length() - a.length()) {
    return true;
  } else {
    return false; 
  }
}

And here's the Oracle docs page on indexOf() in case you want to do some more reading: http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#indexOf(java.lang.String)

Solution 2:[2]

I know this question is ancient but maybe someone will need this information. Here is my solution to String-2 > endOther

public boolean endOther(String a, String b) {
  a = a.toLowerCase();
  b = b.toLowerCase();
  if ((a.endsWith(b)) || (b.endsWith(a))) {
    return true;
  }
  else {
    return false;
  }
}

Solution 3:[3]

My gut feeling is that they want you to use substring. The reason for this is simple: it doesn't matter where else the pattern occurs in either string, so long as it's at the final position(s) of that string.

You also shouldn't (in practice) manipulate the parameters you pass in, since that may trip you up later. Adding final to your param list will prevent you from doing so, just in case you accidentally think that it's doing something you don't.

Lastly, you don't need to convert both strings to lower case at all; there is a method called equalsIgnoreCase which works just fine for this case.

To solve the problem, I've abstracted out a different method to accomplish the main comparison. The logic in the main method only determines which string goes where (since the longer string may be on the right). Below is my solution, which passes all of the tests.

public boolean endOther(final String a, final String b) {
    if (a.length() >= b.length()) {
        return endOtherHelper(a, b);
    } else {
        return endOtherHelper(b, a);
    }
}

private boolean endOtherHelper(final String longStr, final String shortStr) {
    return longStr.substring(longStr.length() - shortStr.length()).equalsIgnoreCase(shortStr);
}

Solution 4:[4]

Look at this code, perhaps you will understand the mistakes:

public boolean endOther(String a, String b) {
  if(a.length() < b.length())
    return b.toLowerCase().substring(b.length()-a.length()).equals(a.toLowerCase());
  else
    return a.toLowerCase().substring(a.length()-b.length()).equals(b.toLowerCase());
}

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 brody
Solution 2 Anil Nivargi
Solution 3 Makoto
Solution 4 Kyll