1

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.

2 Answers2

0

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
0

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)
CristiFati
  • 38,250
  • 9
  • 50
  • 87
  • Thank so much @CristiFati, I took my time to read it and it really benefited me. One question, the result you get (998899) is made of the product of which numbers? Because it is definitely higher than 906609, but the Project Euler's question allowed 906609 as a correct answer. –  Dec 28 '17 at 09:53