Split up your code. You're:
- Generating all triangle numbers.
- Factorizing all triangle numbers.
- Displaying when you get the first triangle number with 500 or more factors. And ending the program.
These sound like some good functions to me.
And so you could use:
def triangle_numbers():
return ...
def factors(number):
return ...
def euler_12():
for number in triangle_numbers():
if len(factors(number)) >= 500:
return number
print(euler_12())
To generate all triangle numbers you can use itertools.count and itertools.accumulate. If you're not running Python 3 you can implement accumulate, or manually perform the calculations yourself.
import itertools
# Python 3
def triangle_numbers():
return itertools.accumulate(itertools.count())
# Python 2
def triangle_numbers():
sum = 0
for i in itertools.count():
sum += i
yield sum
Currently your factors code would be:
def factors(num):
list= []
for j in range(1, num**2):
if (num) % j == 0:
list.append(j)
This has a couple of problems.
You don't need to use
num ** 2. The largest maximum you need isnum + 1.You can use
int(num ** 0.5) + 1.This is as \$\sqrt{n}^2 = n\$. With the equation \$n = a * b\$, allowing you to find \$a\$ when you've found \$b\$.
And so you can use:
def factors(num):
for div in range(1, int(num**0.5) + 1):
if num % div == 0:
yield div
other = num // div
if other != div:
yield other
This has change this piece of code from \$O(n^2)\$ to \$O(\sqrt{n})\$. So if \$n = 10000\$, you'd only need to check \$100\$ numbers, rather than \$100000000\$.
You will also have to change the return value of factors to a list to use len.