0

I've written a simple program in python which checks if the sentence is palindrome. But I can't figure out why isn't it working. The results is always False. Does anyone knows what's wrong?

def isPalindrome(word):
    # Removes all spaces, and lowercase the word.
    word = word.strip().lower()
    word = word.replace(" ", "")

    # If the length of the word is less than 1, means its a palindrome
    if (len(word) <= 1):
        return True

    # Compares the first and the last character of the word.
    # If it is the same, calls the function again with the same word,
    # without its first and last characters. If its not the same, its
    # not palindrome
    else:
        if word[0] == word[-1]:
            isPalindrome(word[1:-1])
        else:
            return False


sentence = input("Enter a sentence: \n")

if (isPalindrome(sentence)):
    print("The sentence %s is palindrome." % sentence)
else:
    print("The sentence %s is NOT palindrome" % sentence)
Eli Korvigo
  • 10,265
  • 6
  • 47
  • 73
Chan Jing Hong
  • 2,251
  • 4
  • 22
  • 41
  • You say that the function always returns `False` but this is not correct, not strictly correct... if you try to substitute your last four statements with `print(isPalindrome(sentence))` you will see that what you print is different in the two possible outcomes.... – gboffi May 17 '15 at 15:19
  • The problem with your code as written, is when you finally do have the string shrunk down to size 0 or 1, it returns True back to the previous incarnation of the recursive function which does not guarantee the final return of the function will be True. But yeah, go with MattDMo's code! – Abd Azrad May 17 '15 at 15:24

7 Answers7

5

You're making this way more complicated than it has to be:

def palindrome(sentence):
    sentence = sentence.strip().lower().replace(" ", "")
    return sentence == sentence[::-1]

sentence[::-1] uses string slicing to reverse the characters in the string.

A slightly more verbose solution that shows how the logic of the return statement above works:

def palindrome(sentence):
    sentence = sentence.strip().lower().replace(" ", "")
    if sentence == sentence[::-1]:
        return True
    else:
        return False
Community
  • 1
  • 1
MattDMo
  • 100,794
  • 21
  • 241
  • 231
  • 2
    Even less complicated if you replace the `if` statement with `return (sentence==sentence[::-1])` – khelwood May 17 '15 at 15:18
  • You'd get my upvote if you removed that ridiculous if-true-false solution :-P – Stefan Pochmann May 17 '15 at 16:27
  • 1
    @StefanPochmann I've rearranged my answer. I kept the more verbose version to demonstrate the logic of the `return` statement, which would be helpful to beginning programmers. Upvote, or not, it's up to you. – MattDMo May 17 '15 at 16:32
  • Yeah, sorry, I just very much dislike that construct in general and appreciate your rearrangement, although I don't really see what you mean with it shows the logic how it works. The `return` doesn't evaluate the truthiness of the thing and then decides to return True or False. That is *not* how it works. It simply returns the thing. – Stefan Pochmann May 17 '15 at 16:44
5

You aren't returning the result of the function.

replace :

if word[0] == word[-1]:
    isPalindrome(word[1:-1])

with

if word[0] == word[-1]:
    return isPalindrome(word[1:-1])
Chaker
  • 1,197
  • 9
  • 22
2

You algorithm is fine, the only problem is that you don't return the true result through the recursion, you have to return the isPalindrome result when calling it recursively:

else:
    if word[0] == word[-1]:
        return isPalindrome(word[1:-1]) #this changed
    else:
        return False
angrykoala
  • 3,774
  • 6
  • 30
  • 55
1

The best way to check a word is palindrome or not in Python is as below:

var[::] == var[::-1]

But, it is very important to understand that Python creates a new copy of string when you do var[::-1] Python internally don't know if the reverse will result in same string or not. So, it's coded in a way where it creates a new copy of it. So, when you try var[::1] is var[::-1] you will get FALSE.

For example:

var = "RADAR" var1 = var[::] var is var1 True var2 = var[0:6:1] var is var2 True var3 = var[::-1] var is var3 False var4 = var[-1:-6:-1] var is var4 False var1 'RADAR' var2 'RADAR' var3 'RADAR' var4 'RADAR'

Here you can see when you move forward, it doesn't creates the copy of "RADAR", it uses the same reference. Because PY internally understand this operation will result in same string object. But, when you move in backward direction, the result can be different. For example, if I do the same operation for "Ethans", then the reverse of it will not be same. So, PY is not aware what will be the result of reversed string and it creates the new copy of it.

Therefore, reversed string is returning false value with 'is' operator.

One more interesting point to note here. See below example:

var = "abc" var1 = "abc" var is var1 True var = "Ethans Baner Pune" var1 = "Ethans Baner Pune" var is var1 False

We know string is immutable and follows Singleton DP, then why the second case is returning FALSE??

This is because PY don't want to compromise on SPEED and PERFORMANCE. If you write a very long string and it's already present in memory, PY should refer to same string. But, finding that long string will take very long time and performance will be decreased. So, rather than referring to existing string, PY instead create a new one. We have also understood this for integers, where it only follow Singleton DP approach till limited value(256).

Let's see one more example:

var = "abcdefgh" var1 = "abcdefgh" var is var1 True var = "abcd efgh" var1 = "abcd efgh" var is var1 False

Manpreet
  • 125
  • 3
  • 11
0

You need to replace "input" with "raw_input". Also, you are calling isPalindrome recursively and there is a mistake here as well. It should be:

if word[0] == word[-1]:
    return isPalindrome(word[1:-1])
else:
    return False

Check the corrected code below:

def isPalindrome(word):
    # Removes all spaces, and lowercase the word.
    word = word.strip().lower()
    word = word.replace(" ", "")

    # If the length of the word is less than 1, means its a palindrome
    if (len(word) <= 1):
        return True

# Compares the first and the last character of the word.
# If it is the same, calls the function again with the same word, without its first and last characters.
# If its not the same, its not palindrome
    if word[0] == word[-1]:
        return isPalindrome(word[1:-1])
    else:
        return False


sentence = raw_input("Enter a sentence: \n")

if (isPalindrome(sentence)):
    print("The sentence %s is palindrome." % sentence)
else:
    print("The sentence %s is NOT palindrome" % sentence)
Nipun Talukdar
  • 4,975
  • 6
  • 30
  • 42
0

I presume this is an assignment and the recursion is necessary, obviously return word == word[::-1] is simpler but is not really relevant. You can write your recursive function a bit more succinctly:

def isPalindrome(word):
    if not word:
        return True
    return word[0] == word[-1] and isPalindrome(word[1:-1])

word[0] == word[-1] will either be True or False so you will either reach an empty string where not word will True so the recursion ends and the function returns True or word[0] == word[-1] will be False so the function will return False as and isPalindrome(word[1:-1]) will never be evaluated.

I would also maybe do the lowering outside of the function:

def isPalindrome(word):
    if not word:
        return True
    return word[0] == word[-1] and isPalindrome(word[1:-1])


sentence = input("Enter a sentence: \n")
sentence = sentence.strip().lower()
sentence = sentence.replace(" ", "")
if isPalindrome(sentence):
    print("The sentence %s is palindrome." % sentence)
else:
    print("The sentence %s is NOT palindrome" % sentence)
Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
0

Since the mistake is already explained and the obvious s == s[::-1] is already taken, I'll just throw a possibly minimal version of the original into the mix:

def isPalindrome(s):
    s = s.strip().lower()
    return not s or s[0] == s[-1] and isPalindrome(s[1:-1])

Note that you don't need replace(" ", ""). Space on the outside is removed with strip() now, and spaces on the inside will be removed by the strip() later, in a call deeper into the recursion (if we don't stop earlier because a s[0] == s[-1] fails).

Stefan Pochmann
  • 27,593
  • 8
  • 44
  • 107