Search code examples
pythonalgorithmpalindrome

Finding the largest palindrome product of two 3-digit numbers: what is the error in logic?


I thought of solving this problem in the following way: start with two variables with value 999, multiplying one by another in a loop that decrements one or the other until a palindrome is found. The code is this:

def is_palindrome(n):
  if str(n) == str(n)[::-1]:
    return True
  else:
    return False

def largest_palindrome_product_of_3_digit():
  x = 999
  y = 999
  for i in reversed(range(x + y + 1)):
    if is_palindrome(x * y):
      return x * y
    if i % 2 == 0:
      x -= 1
    else:
      y -= 1

The result of my method is 698896, while the correct result is 906609. Could you point me where my logic is incorrect?


Solution

  • Here are a couple of hints:

    1. If n=y*x is any number in the range(600000, 700000) (for example) with y<=x, and x<1000, what's the smallest possible value of x?
    2. If n is a palindromic number, both its first and last digit are 6, so what does that imply about the last digits of x & y?

    Now generalize and figure out an efficient algorithm. :)

    I've never done this problem before, but I just coded a reasonably fast algorithm that's around 2000 times faster than a brute-force search that uses

    for x in xrange(2, 1000): 
        for y in xrange(2, x+1):
            n = y*x
            #etc
    

    According to timeit.py, the brute-force algorithm takes around 1.29 seconds on my old machine, the algorithm I hinted at above takes around 747 microseconds.


    Edit

    I've improved my bounds (and modified my algorithm slightly) and brought the time down to 410 µsec. :)

    To answer your questions in the comment:

    Yes, we can start x at the square root of the beginning of the range, and we can stop y at x (just in case we find a palindromic square).

    What I was getting at with my 2nd hint is that for x=10*I+i, y=10*J+j, we don't need to test all 81 combinations of i and j, we only need to test the ones where (i*j)%10 equals the digit we want. So if we know that our palindrome starts and ends with 9 then (i, j) must be in [(1, 9), (3, 3), (7, 7), (9, 1)].

    I don't think I should post my actual code here; it's considered bad form on SO to post complete solutions to Project Euler problems. And perhaps some SO people don't even like it when people supply hints. Maybe that's why I got down-voted...