Reputation: 1
I am experiencing some running time issues with Project Euler. The exercise can be found here: Project Euler exercise 12. My solution is:
def triangularnr(n):
T_n = n*(n+1)/2 #Function to calculate triangular numbers
return T_n
for n in range(1,1*10**8): #Nr with over 500 divisors is large, large range required
count = 2 #Every nr is divisible by itself and by 1, thus initially count = 2
for i in range(2,int(triangularnr(n))): #Defining i to find divisors
if triangularnr(n)%i == 0:
count+=1 #Incrementing count to count the nr of divisors
if count > 500: #If a triangularnr has over 500 divisors we want to print the nr
print(triangularnr(n))
break
I've tried to optimize the code by reducing the nr of steps required and by using a mathematical formula for triangular numbers. My code works for 5 divisors, but it takes ages to find 500 divisors. I've let the code run for 3 hours yesterday and still no output. Should I let the code run for more than 3 hours, or will the output never be printed as there is something wrong with my code?
Upvotes: 0
Views: 68
Reputation: 24420
This is more a mathematical answer than a programming one, but one way to improve your algorithm is to think about how to determine the number of divisors of a number.
The brute force way would be to iterate over all numbers smaller than your test number and check every one of them but this is not very efficient for large numbers as you found out.
A more efficient way would be to consider the prime decomposition of your test number. Any integer can be written as the product of prime numbers. Suppose that N has prime factors p1
, p2
,... , pn
with exponents k1
, k2
,... ,kn
, i.e. N == p1**k1 * p2**k2 * ... * pn**kn
, then the number of divisors of N
is equal to (k1+1)*(k2+1)*...*(kn+1)
. So finding the number of divisors is equivalent to finding the prime factors of a number which restricts the number of integers you need to check considerably.
Another thing to realize is that if integers N1
and N2
have no prime factors in common (which is the case for N
and N+1
), the number of divisors of N1*N2
is equal to the number of divisors of N1
times the number of divisors of N2
. This means that since you are considering numbers of the form N*(N+1)//2
and since N
and N+1
have no prime factors in common, the number of divisors of your triangular numbers is equal to the product of the number of divisors of N//2
and the number of divisors of N+1
for even N
, and to the product of the number of divisors of N
and the number of divisors of (N+1)//2
for odd N
.
Upvotes: 2
Reputation: 1081
Firstly, as a rule of thumb, for most project Euler exercises your code should take less than a minute to run. Remember, questions on project Euler challenge your ability to come up with interesting solutions, not to brute force answers.
Your algorithm is inefficient because:
These two things mean that your algorithm probably has a complexity of n^3. Eg. doubling the required number of factors increases the search space by a factor of 8.
One tip that might prove useful is that if you have two numbers, a and b, the number of factors of a*b is equal to the number of factors of a multiplied by the number of factors of b. For example 5 has two factors (5, 1) and 14 has 4 factors (1, 2 ,7 and 14). From this we know that 5*14 has 2*4 factors, without having to search the numbers from 1 to 70.
Lucky for you the triangular number formula T_n = n * (n + 1) / 2
already comes broken down into two factors, so you need to code something to:
n
or n + 1
is evenHope that helped :)
Upvotes: 1