from lib_misc import is_palindrome def euler_004(): r = 0 for a in range(999, 99, -1): for b in range(a, r // a, -1): if is_palindrome(a * b) and a * b > r: r = a * b return r def euler_004_original(): """ The solution that I came up with originally. """ r = 0 for a in range(999, 99, -1): if a * a < r: break for b in range(a, 99, -1): c = a * b if c > r and is_palindrome(c): r = c return r def euler_004_forum(): """ A solution from etatsui in the project Euler forum. It is impressive to see how much fast it is relying on mathematical tricks: 11(9091a + 910b + 100c) = mn; Let: 11 * 10 < m < 11 * 90 """ for a in range(9, 0, -1): for b in range(9, -1, -1): for c in range(9, -1, -1): num = 9091 * a + 910 * b + 100 * c for m in range(90, 9, -1): if num % m == 0: if num / m > 999: break else: result = num * 11 return result assert(euler_004() == 906609) print("e004.py: {}".format(euler_004())) def time_tests(): from timeit import timeit assert(euler_004() == 906609) assert(euler_004_original() == 906609) assert(euler_004_forum() == 906609) print(timeit(lambda: euler_004(), number=100)) print(timeit(lambda: euler_004_original(), number=100)) print(timeit(lambda: euler_004_forum(), number=100)) # time_tests() # 0.5044660240000667 # 0.7896412069985672 # 0.04794573199978913