def is_palindrome(x, pos_index, neg_index):
if x[pos_index] == x[neg_index]:
print("")
else:
return False
pos_index += 1
neg_index -= 1
is_palindrome(x, pos_index, neg_index)
print(is_palindrome("racecar", 0, -1))

- 43,494
- 9
- 68
- 117

- 11
- 3
-
Welcome to StackOverflow. Please explain in more detail what is not working. Just pasting the code is not enough. Also have a look at [how to ask a good question](https://stackoverflow.com/help/how-to-ask) – Dominik Mar 10 '21 at 15:25
-
Am sorry Dominik this is my first question, I am getting an index out of range error when I run that particular code in pycharm? – Ronnie Atuhaire Mar 10 '21 at 15:29
5 Answers
Your end condition is missing. You recall the function every time, so your pos_index becomes 6 ('r'). After that you should stop, but instead you add one and start the function again. So you get a String index out of range.
And a little note, for your next question some addition information or a specific question would be nice.

- 476
- 2
- 9
The reason you get an error is because is_palindrome()
calls is_palindrome()
continuously and there is no stop if the word is a palindrome. The function will only return if the word is not a palindrome. Since there is no stopping point, eventually, both the positive and negative indexes will exceed the maximum index of the string. I would try using this:
def is_palindrome(phrase):
phrase = "".join(phrase.lower().split())
index, imax = 0, len(phrase)-1
while index < imax-index:
if phrase[index] != phrase[imax-index]:
return False
index += 1
return True
Note that this only checks until index
is as close to the halfway through the string as possible (which can be observed by putting print(index)
inside the while
loop). That way, the code doesn't "double-check" the second half of the string.
Below are a few test runs:
>>> is_palindrome("racecar")
True
>>> is_palindrome("bus")
False
>>> is_palindrome("a man a plan a canal panama")
True
>>> is_palindrome("AABBAA")
True
However, if you wanted to conserve the recursive nature, you can try using this:
def is_palindrome(phrase, positive=0, negative=-1):
phrase = ''.join(phrase.lower().split())
if positive >= len(phrase):
return True
if phrase[positive] == phrase[negative]:
return is_palindrome(phrase, positive+1, negative-1)
return False
A few test runs:
>>> is_palindrome("racecar")
True
>>> is_palindrome("bus")
False
>>> is_palindrome("A man a plan a canal panama")
True
>>> is_palindrome("AABBAA")
True

- 4,405
- 2
- 16
- 37
-
The OP's solution is recursive in nature and they tagged [recursion] but your solution doesn't appear to recurse. – cdlane Mar 10 '21 at 17:10
If I were to fix your code, and preserve most of it, I would do something like:
def is_palindrome_recursive(x, pos_index, neg_index):
if -neg_index >= len(x):
return True
if x[pos_index] != x[neg_index]:
return False
pos_index += 1
neg_index -= 1
return is_palindrome_recursive(x, pos_index, neg_index)
def is_palindrome(string):
return is_palindrome_recursive(string, 0, -1)
print(is_palindrome("racecar"))
Where the major changes are: an additional return
case when we've recursively reduced the input to one letter or less; deal with the result of our recursive call -- a common recursion beginner error.
Since this is not an inherently mathematical problem, my inclination would be to get the numbers and mathematical operators out of the solution. I would also treat the argument as a sequence, rather than a string, to allow fluid transition between a str
and a list
of characters:
def is_palindrome(sequence):
if sequence:
first, *rest = sequence
if rest:
*middle, last = rest
if first != last:
return False
return is_palindrome(middle)
return True
if __name__ == "__main__":
print(is_palindrome("racecar"))
print(is_palindrome("radar"))
print(is_palindrome("ABBA"))
print(is_palindrome("pop"))
print(is_palindrome("cc"))
print(is_palindrome("I"))
print(is_palindrome(""))
I expect a recursive predicate function for this problem to have three return
possibilities: return True
on success; return False
on failure; return is_palindrome(...)
a recursive I don't know, yet.

- 40,441
- 5
- 32
- 81
Try this:
def is_palindrome(x, pos_index, neg_index):
if x[pos_index] == x[neg_index]:
print("")
else:
return False
if pos_index==len(x)-1:
exit()
else:
pos_index += 1
neg_index -= 1
is_palindrome(x, pos_index, neg_index)
print(is_palindrome("racecar", 0, -1))

- 339
- 1
- 14
-
2From the name `is_*`, I would expect a predicate function, i.e. one that returns `True` or `False`. This function does one of *three* things, it may return `False`, it might return `None`, or it might kick you out of Python! – cdlane Mar 10 '21 at 17:07
Recursion is a functional heritage and so using it with functional style yields the best results. This means avoiding things like mutations, variable reassignments, and other side effects -
- if the input string,
s
, is less than 2 characters, we always have a palindrome. Return true. - (inductive)
s
is 2 characters or more. If the first character does not match the last character, return false - (inductive)
s
is 2 characters or more and the first character matches the last character. Return the result of the sub-problem,s[1:-1]
def is_palindrome(s):
if len(s) < 2:
return True #1
elif s[0] != s[-1]:
return False #2
else:
return is_palindrome(s[1:-1]) #3
is_palindrome("racecar")
is_palindrome("aceca")
is_palindrome("cec")
is_palindrome("e")
True
We can collapse the bottom two logical branches into one -
def is_palindrome(s):
if len(s) < 2:
return True
else:
return s[0] == s[-1] and is_palindrome(s[1:-1])
Finally we could collapse the if
altogether and simply use logical operators for the entire expression -
def is_palindrome(s):
return len(s) < 2 or s[0] == s[-1] and is_palindrome(s[1:-1])

- 129,518
- 31
- 228
- 259