I'm doing this dime-a-dozen recursion problem, whereby we must return the first index, where a substring occurs in a larger string. If it is not found, return -1. Helper functions are not encouraged.
indexOf("Hello", "Lo") --> 3
, because "lo" first appears at index 3.
indexOf("Hello", "H") --> 0
, because "H" first appears at index 0.
indexOf("Hello", "x") --> -1
, because "x" does not appear at all.
Here's the good news though: I already figured it out!
public static int indexOf(String s1, String s2) {
//Invalid cases: empty string or invalid input, where s1 length is less than the substring length.
//Base case: If s1, sliced to the same length as s2, equals s2, then return 0.
//Otherwise, return recursively + 1.
if (s1.length() == 0 | s1.length() < s2.length()) {
return -1;
} else if (s1.substring(0, s2.length()).equals(s2)) {
return 0;
}
return indexOf(s1.substring(1, s1.length()), s2) + 1;
}
So if it works, what is the problem? The problem is the whole returning -1 thing. It returns the correct index of substrings, but invalid inputs do not return -1. This recursive function is build on the idea, that as it traverses further down the substring, it would be taking and index along with it, so if not found in "hello", it would go to "ello" and tuck a 1 index under its hat, since we know at this point that the index, if it exists, would be at least 1.
The problem is though, as the stack frames go deeper, they are constantly incrementing by 1, so the -1 doesn't have an effect. If I set s2 to be something like "x", it simply returns "4", the number of times it traverses the substrings of "hello". Without a number to keep track of stack frames, I can't make it equal -1 by saying "return -5" or whatever. Is there a way for it to travel through the whole string, constantly incrementing by 1, yet somehow at the very end, return a -1 if s2 is not found?
Hard-coded version (my favourite recursion strategy):
public static int indexOf(String s1, String s2) {
if (s1.length() == 0 | s1.length() < s2.length()) {
return -1;
} else if (s1.substring(0, s2.length()).equals(s2)) {
return 0;
} else if (s1.substring(1, 1 + s2.length()).equals(s2)) {
return 0 + 1;
} else if (s1.substring(2, 2 + s2.length()).equals(s2)) {
return 0 + 1 + 1;
} else if (s1.substring(3, 3 + s2.length()).equals(s2)) {
return 0 + 1 + 1 + 1;
} else if (s1.substring(4, 4 + s2.length()).equals(s2)) {
return 0 + 1 + 1 + 1 + 1; //what the other function returned + 1
}
return -1;
}
It works absolutely perfectly in this hard-coded way. I realized that the problem is that last "return -1", which would actually have to go at the beginning rather than the end for it to work. I only show this in case it helps out.