Eulers problem №3, code stucks on big numbers

Viewed 72

I'm currently learning Python, and practice with euler's problem's. I'm stuck on 3rd problem, my code didn't working on the big numbers, but with other number's it's working.

n = 600851475143 
x = 0
for i in range(2,n):
    if(n%i == 0):
        if(x < i): x = i
print(x)

The console just didn't get any results and stucks. P.S https://projecteuler.net/problem=3

(sorry for my bad english)

4 Answers

It's running, but just the time it takes is huge. You can check by the following code, it keeps going to print x's.

n = 600851475143
x = 0
for i in range(2, n):
    if n % i == 0:
        if x < i:
            x = i
            print(x)

To save time, you can try the following code instead of your code:

n = 600851475143
x = 0
for i in range(2, n):
    if n % i == 0:
        x = n // i
        break
print(x) 

which prints 8462696833 instantly. But as @seesharper stated on the comment, it is merely the largest factor and not a prime factor. So it is not the correct answer to the Project Euler Problem #3.

from tqdm.auto import tqdm

n = 600851475143 
x = 0
for i in tqdm(range(2,n)):
    if(n%i == 0):
        x = i
print(x)

If using classic python, your program will last for at least 40 min, that's why you had no output. I suggest you either use numpy to go through, or add a step because I think even numbers won't work.

I used tqdm to estimate the time needed for the for loop to run, you can download it using pip install tqdm

Check this code you will save a lot of time

Using sqrt for optimization

from math import sqrt
def Euler3(n):
    x=int(sqrt(n))
    for i in range(2,x+1):
        while n % i == 0:
            n //= i
            if n == 1 or n == i:
                return i
    return n
n = int(input())
print(Euler3(n))

Also, check my Euler git repo

There are only 6 solutions in python2 and it's pretty old but they are very well optimized.

What would be more efficient is to only divide your number by actual primes. You also only need to check divisors up to the square root of the number given that any valid (integer) result will be also be a divisor (which you will already have checked if your divisor goes beyond the square root).

# generator to obtain primes up to N
# (sieve of Eratosthenes)

def primes(N):
    isPrime = [True]*(N+1)
    p = 2
    while p<=N:
        if isPrime[p]:
            yield p
            isPrime[p::p] = (False for _ in isPrime[p::p])
        p += 1 + p>2

# use the max function on primes up to the square root 
# filtered to only include those that divide the number

n = 600851475143        
result = max(p for p in primes(int(n**0.5)+1) if n%p == 0)

print(result) # 6857

Alternatively, you can use sequential divisions to find factors while reducing the number as you go along. This will cause each new factor you find to be a prime number because divisions by all smaller numbers will already have been done and removed from the remaining number. It will also greatly reduce the number of iterations when your number has many prime factors.

def primeFactors(N): # prime factors generator
    d,d2 = 2,4                 # start divisors at first prime (2)
    while d2<=N:               # no need to go beyond √N
        if N%d: 
            d += 1 + (d&1)     # progress by 2 from 3 onward
            d2 = d*d           # use square of d as limiter
        else:
            yield d            # return prime factor
            N //= d            # and reduce number
    if N>1: yield N            # final number could be last factor

print(*primeFactors(600851475143)) # 71 839 1471 6857
            
print(max(primeFactors(600851475143))) # 6857
Related