Chris
Chris

Reputation: 25

Palindrome generator

Very inexperienced with python and programming in general.

I'm trying to create a function that generates a list of palindromic numbers up to a specified limit.

When I run the following code it returns an empty list []. Unsure why this is so.

def palin_generator():
    """Generates palindromic numbers."""

    palindromes=[]
    count=0
    n=str(count)

    while count<10000:
        if n==n[::-1] is True:
            palindromes.append(n)
            count+=1
        else:
            count+=1

    print palindromes  

Upvotes: 1

Views: 10168

Answers (3)

Martin Thoma
Martin Thoma

Reputation: 136287

Going through all numbers is quite inefficient. You can generate palindromes like this:

#!/usr/bin/env python
from itertools import count

def getPalindrome():
    """
        Generator for palindromes.
        Generates palindromes, starting with 0.
        A palindrome is a number which reads the same in both directions.
    """
    yield 0
    for digits in count(1):
        first = 10 ** ((digits - 1) // 2)
        for s in map(str, range(first, 10 * first)):
            yield int(s + s[-(digits % 2)-1::-1])

def allPalindromes(minP, maxP):
    """Get a sorted list of all palindromes in intervall [minP, maxP]."""
    palindromGenerator = getPalindrome()
    palindromeList = []
    for palindrome in palindromGenerator:
        if palindrome > maxP:
            break
        if palindrome < minP:
            continue
        palindromeList.append(palindrome)
    return palindromeList

if __name__ == "__main__":
    print(allPalindromes(4456789, 5000000))

This code is much faster than the code above.

See also: Python 2.x remarks.

Upvotes: 4

Martijn Pieters
Martijn Pieters

Reputation: 1121634

Your if statement does not do what you think it does.

You are applying operator chaining and you are testing 2 things:

(n == n[::-1]) and (n[::-1] is True)

This will always be False because '0' is True is not True. Demo:

>>> n = str(0)
>>> n[::-1] == n is True
False
>>> n[::-1] == n 
True

From the comparisons documentation:

Comparisons can be chained arbitrarily, e.g., x < y <= z is equivalent to x < y and y <= z, except that y is evaluated only once (but in both cases z is not evaluated at all when x < y is found to be false).

You do not need to test for is True here; Python's if statement is perfectly capable of testing that for itself:

if n == n[::-1]:

Your next problem is that you never change n, so now you'll append 1000 '0' strings to your list.

You'd be better off using a for loop over xrange(1000) and setting n each iteration:

def palin_generator():
    """Generates palindromic numbers."""

    palindromes=[]

    for count in xrange(10000):
        n = str(count)
        if n == n[::-1]:
            palindromes.append(n)

    print palindromes  

Now your function works:

>>> palin_generator()
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '11', '22', '33', '44', '55', '66', '77', '88', '99', '101', '111', '121', '131', '141', '151', '161', '171', '181', '191', '202', '212', '222', '232', '242', '252', '262', '272', '282', '292', '303', '313', '323', '333', '343', '353', '363', '373', '383', '393', '404', '414', '424', '434', '444', '454', '464', '474', '484', '494', '505', '515', '525', '535', '545', '555', '565', '575', '585', '595', '606', '616', '626', '636', '646', '656', '666', '676', '686', '696', '707', '717', '727', '737', '747', '757', '767', '777', '787', '797', '808', '818', '828', '838', '848', '858', '868', '878', '888', '898', '909', '919', '929', '939', '949', '959', '969', '979', '989', '999', '1001', '1111', '1221', '1331', '1441', '1551', '1661', '1771', '1881', '1991', '2002', '2112', '2222', '2332', '2442', '2552', '2662', '2772', '2882', '2992', '3003', '3113', '3223', '3333', '3443', '3553', '3663', '3773', '3883', '3993', '4004', '4114', '4224', '4334', '4444', '4554', '4664', '4774', '4884', '4994', '5005', '5115', '5225', '5335', '5445', '5555', '5665', '5775', '5885', '5995', '6006', '6116', '6226', '6336', '6446', '6556', '6666', '6776', '6886', '6996', '7007', '7117', '7227', '7337', '7447', '7557', '7667', '7777', '7887', '7997', '8008', '8118', '8228', '8338', '8448', '8558', '8668', '8778', '8888', '8998', '9009', '9119', '9229', '9339', '9449', '9559', '9669', '9779', '9889', '9999']

Upvotes: 3

recursive
recursive

Reputation: 86064

Your if block checks whether n is a palindrome, and the value of n never changes. It's only assigned once.

Also, you can eliminate the is True part because that is redundant.

But that's not the root of your problem now. In fact, the reason your if is failing is operator precedence. What you've written now is equivalent to if n==(n[::-1] is True): which is if n==False:, which will never happen.

Upvotes: 0

Related Questions