简体   繁体   中英

Project Euler: Largest palindrome product of two 3-digit number

I get 580085 , why is it wrong? And is there another way to check whether a number is a palindrome?

def reverse(str, aux=''):
    count = len(str)
    while count > 0:
        aux += str[count-1]
        count -= 1
    return aux

def palindrome(num):
    j = str(num)
    if j == reverse(j):
        return 1
    else:
        return 0

i = 999
found = 0
while i > 99 and not found:
    j = 999
    while j > 99 and not found:
        if palindrome(i * j):
            found = 1
            print(i * j)
        else:
            j -= 1
    if not found:
        i -= 1

My post is mostly code, but I don't have anything else to say.

New code:

def reverse(str, aux=''):
    count = len(str)
    while count > 0:
        aux += str[count-1]
        count -= 1
    return aux

def palindrome(num):
    j = str(num)
    if j == reverse(j):
        return 1
    else:
        return 0

i = 999
max = 0
while i > 99:
    j = 999
    while j > 99:
        num = i * j
        if palindrome(num):
            if num > max:
                max = num
                print(max)
        j -= 1
    i -= 1

Took some time and studied the problem. I tried taking the reversed approach (starting from palindrome numbers, and find their dividers (if any)). Using Py354 on Win10 .

code.py :

import time
from math import sqrt


def reverse(str, aux=''):
    count = len(str)
    while count > 0:
        aux += str[count-1]
        count -= 1
    return aux


def palindrome(num):
    j = str(num)
    if j == reverse(j):
        return 1
    else:
        return 0


def question_makhfi_0():
    ret = 0
    i = 999
    found = 0
    while i > 99 and not found:
        j = 999
        while j > 99 and not found:
            if palindrome(i * j):
                found = 1
                ret = i * j
            else:
                j -= 1
        if not found:
            i -= 1
    return ret, i, j


def answer_makhfi_0():
    i = 999
    _max = 0
    while i > 99:
        j = 999
        while j > 99:
            num = i * j
            if palindrome(num):
                if num > _max:
                    _max = num
                    factor0, factor1 = i, j
            j -= 1
        i -= 1
    return _max, factor0, factor1


"""
def answer_makhfi__0_improved_0():
    i = j = 999
    prod = i * j
    step = 0
    while prod > 100000:
        if step % 2:
            i -= 1
        else:
            j -= 1
        prod = i * j
        prod_str = str(prod)
        if prod_str == prod_str[::-1]:
            return prod
        step += 1
"""


def answer_cfati_0():
    pal = 999999
    while pal >= 900009:
        if pal % 10 == 9:
            pal_str = str(pal)
            if pal_str == pal_str[::-1]:
                pal_sqrt = sqrt(pal)
                for factor0 in range(101, int(pal_sqrt) + 1):
                    if pal % factor0 == 0:
                        factor1 = int(pal / factor0)
                        if 100 <= factor1 <= 999:
                            return pal, factor0, factor1
        pal -= 10
    #return pal


def time_func(f, *args):
    t0 = time.time()
    res = f(*args)
    t1 = time.time()
    return t1 - t0, res


if __name__ == "__main__":
    for func in [question_makhfi_0, answer_makhfi_0, answer_cfati_0]:
        print("\nStarting: {}".format(func.__name__))
        #print(func.__name__)
        res = time_func(func)
        print("  Time: {:.6f}\n  Result: {}".format(*res))

Notes :

  • Turned your code into functions (doing all required adjustments, and omitting everything that involves performance)
  • Added an additional func that measures execution time
  • answer_makhfi_0 :
    • replaced max by _max to avoid shadowing builtin names
    • added a return statement at the end (highly inefficient, anyway)
  • answer_cfati_0 :
    • The code assumes there's a palindrome number in the [900009, 999999] range, that can be expressed as a 2 (3 digit) numbers product. It's fair to assume that (tests support this). However if aiming for bullet proof code, this form won't do it, I'll have to adjust it a bit (it will be a loss performance-wise)
    • It uses all kinds of mathematical/logical "shortcuts" to avoid computing uselessly (I think code could also be improved on that direction).

Output :

 "e\\Work\\Dev\\StackOverflow\\q47999634>"e:\\Work\\Dev\\VEnvs\\py35x64_test\\Scripts\\python.exe" code.py Starting: question_makhfi_0 Time: 0.008551 Result: (580085, 995, 583) Starting: answer_makhfi_0 Time: 1.457818 Result: (906609, 993, 913) Starting: answer_cfati_0 Time: 0.012599 Result: (906609, 913, 993) 

According to the output, differences between original and new code (for one run, as times vary):

  • Largest palindrome number: 906609 - 906609
  • Time to calculate it: 1.457818 - 0.012599

@EDIT0 :

  • Thanks to your comment, I found a (critical) logical error (and some small ones) in my code: it was returning 998899 ( 781 * 1279 ). After fixing them, the performance decreased by one order of magnitude, but it's still fast
  • Modified functions to also return the factors (for checking)

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