简体   繁体   中英

Why doesn't str(a) == reversed(str(a)) work as a palindrome test in Python?

I have been trying to find the answer to problem #4 in Project Euler in Python but I really can´t seem to find the problem in my code. Here is the question:

A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99. Find the largest palindrome made from the product of two 3-digit numbers.

And here is my code:

nums = list(range(10000, 998001))

pals = []
def palindrome(a):
    if str(a) == reversed(str(a)):
        pals.append(a)

for every in nums:
    palindrome(every)

For a start, try printing out the string and its supposed reversal - you'll find they're not as you expect. A more sensible way of getting the string reversal of s is with s[::-1] .

Then you need to realise that you're checking every number in that range of yours, 10000..998000 (noticing I've left out 998001 there since Python ranges are exclusive at the end). Not all of those numbers will be a product of two 3-digit numbers. Of course, it may be that was going to be your next step once you'd got all the palindromes, in which case feel free to ignore this paragraph (other than fixing the range, of course).


As an aside, I probably wouldn't wrap that range in a list. If you're using Python 2, it's already a list and, for Python 3, it's probably better to leave it as a lazy iterator so as not to waste memory.


And, as a final aside, I probably wouldn't do it this way since I prefer readable code but those who demand "Pythonic" solutions may like to look at something like:

print(max((i*j
    for i in range(100,1000)
    for j in range(100,1000)
    if str(i*j) == str(i*j)[::-1]
    )))

though of course true Python aficionados will want that on a single line :-) I've just split it for readability.

Python's reversed returns an iterator object. So, no one string could be equal to the iterator.

Because reversed returns an iterator object, you should replace str(a) == reversed(str(a)) with str(a) == str(a)[::-1] . The [::-1] qualifier is a string splicing that will reverse the collection.

Let me start with what everyone else pointed out: reversed(s) is not the same as s[::-1] .

Everyone else wanted you to use s[::-1] instead of reversed() . Sure, that suggestion is scrutable and idiomatic. But why limit yourself! This is Python, after all.

from itertools import combinations, ifilter, imap, starmap
from operator import eq, mul

def is_palindrome(integer):
    """Returns a True if an input integer's digits are palindromic, False otherwise."""
    string = str(integer) 
    return all(imap(eq, iter(string), reversed(string)))

def largest_palindrome_product(n_digits=3):
    """Solves Project Euler #4"""
    all_n_digit_numbers = xrange(10**(n_digits)-1, 10**(n_digits-1), -1)
    palindromes = ifilter(is_palindrome, 
                          (starmap(mul, combinations(all_n_digit_numbers, 2)))
                         )
    return max(palindromes)

largest_palindrome_product()

This solution has the valuable feature of retaining the use of reversed() ! For extra inscrutability I tried to use as many functions from itertools as I could.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM