Quester
Quester

Reputation: 2009

Recursive Program: What am I doing wrong?

I am trying to write a code that would analyze if a word is a palindrome. BTW a palindrome is a word that is read the same backward and forward. Example are "madam" or "noon"

Here is a try:

x = raw_input("please enter a word:\n")
L = len(x)

 # this part returns the first letter of the word

def first(word):
    return word[0]

# this part returns the last letter of the word

def last(word):
    return word[-1]


def middle(word):
    return word[1:-1]


def is_palindrome(word):
    if L <= 2:
        print 'enter a word with at least three letters'
    elif first(word) != last(word):
        print 'This word is not a palindrome'
    else:
        word = middle(word)
        is_palindrome(word)

is_palindrome(x) 

But when executed, I get

IndexError: string index out of range
...line 7, in first return word[0]

The first branch of "is_palindrome" works perfectly. i.e. when the word is not a palindrome, I get no errors. Like "noopn" is executed with no errors, but the error is in the second branch

I've playing with this code for so many times but can't figure out the "iterative part" I have the answer but I don't want to look at it yet. I need to figure out two things: 1. a way to make the iteration in the function is_palindrome work correctly? and 2. a way to exit the program in the end.

Could you folks direct me to how to answer these questions without providing the solution yet?

Finally where should I put the print statement: print 'This word is a palindrome'

Thank you

Upvotes: 1

Views: 709

Answers (6)

Quester
Quester

Reputation: 2009

Great directions guys. All got an upvote.

These directions allowed me to make the following concise codes

Code 1

x = raw_input("enter a word to check if it is a palindrome:\n")

if x[::-1] == x:
    print 'yes this one is a palindrome'

else:
    print 'sorry try again by re-running the program'


Code 2

x = raw_input("enter a word to check if it is a palindrome:\n")

if len(x) <= 1:
    print 'Of course ', x, ' is a palindrome'

def is_palindrome(x):    
    if len(x) >= 2:
        if x[0]!=x[-1]:
            print 'This is not a palindrome'
        else:
            x = x[1:-1]
            return is_palindrome(x)
    print 'This is FINALLY a real palindrome'

is_palindrome(x)

I guess I could include the function is_palindrome as a second branch of the conditional statement len(x) <= 1, but I like it better this way since the code is all about this function

Upvotes: 0

Chris L
Chris L

Reputation: 53

A basic version without considering capitalization and white-space, I'd suggest:

def is_palindrome(word):
    if len(word) < 3:
        print 'Enter a word with at least three letters'
    else:
        for letter in range(len(word)/2):
            if word[letter] != word[-letter - 1]:
                print "This word is not a palindrome"
                return
        print "This word is a palindrome"

Though I think it might personally remove white space and make the comparisons using .lower(). Then it will be case insensitive and allow for testing a phrase or sentence also.

Upvotes: 1

glglgl
glglgl

Reputation: 91017

Personally, I would prefer separating the check and the output. So is_palindrome() should just return the answer and not be responsible for telling the user. That makes it more reusable.

def is_palindrome(word):
    # handle the base case
    if len(word) <= 1:
        return True
    elif first(word) != last(word):
        return False
    else:
        word = middle(word)
        return is_palindrome(word)

This enables you to do

x = raw_input("please enter a word:\n")
L = len(x)

if L <= 2:
    print 'enter a word with at least three letters'
elif is_plaindrome(word):
    print 'This word is a palindrome'
else:
    print 'This word is not a palindrome'

This puts the validity check to the front of the execution, while in the recursion, you have only the checks which are valid all over the recursion.

(I doubt if your check is necessary at all - are y and oo no palindromes? We could argue about the empty string, however...)

The next improvement steps could be to omit the functions first(), last() and middle() - they are trivial and only used once, so you could put there code where they are used.

Upvotes: 2

misguided
misguided

Reputation: 3789

Added an extra condition in your code , which will solve your problem. You don't need to call is_palindrome() , when you have just a single character left

    x = raw_input("please enter a word:\n")
    L = len(x)

     # this part returns the first letter of the word

    def first(word):
        return word[0]


   # this part returns the last letter of the word

    def last(word):
        return word[-1]


    def middle(word):
        return word[1:-1]


    def is_palindrome(word):
        if L <= 2:
            print 'enter a word with at least three letters'
        elif first(word) != last(word):
            print 'This word is not a palindrome'
        else:
            word = middle(word)
            if len(word) > 1:
                is_palindrome(word)
            else:
                print 'This word is a palindrome'

    is_palindrome(x)

Upvotes: 1

jh314
jh314

Reputation: 27802

You need a base case for your recursion. A one letter word is a palindrome, and an empty string is also a palindrome.

def is_palindrome(word):
    # handle the base case
    if len(word) <= 1:
        print 'This word is a palindrome'
    elif first(word) != last(word):
        print 'This word is not a palindrome'
    else:
        word = middle(word)
        is_palindrome(word)

If you want to reject words with fewer than three letters, then you can use a helper function that calls the recursive function:

def is_palindromeHelper(word):
    if len(word) <= 2:
        print 'enter a word with at least three letters'
    else:
        is_palindrome(word)

Upvotes: 3

zhangyangyu
zhangyangyu

Reputation: 8610

To accomplish your goal, why don't just use:

string[::-1] == string

And the reason for your answer is when there is only 1 letter, middle will return an empty string and then ''[0] will cause the error.

Upvotes: 4

Related Questions