I am studyng recursion in Python and now I am having a problem with this exercise:
Remember that Fibonacci's sequence is a sequence of numbers where every number is the sum of the previous two numbers.
For this problem, implement Fibonacci recursively, with a twist! Imagine that we want to create a new number sequence called Fibonacci-3. In Fibonacci-3, each number in the sequence is the sum of the previous three numbers. The
sequence will start with three 1s, so the fourth Fibonacci-3
number would be 3 (1+1+1), the fifth would be 5 (1+1+3), the sixth would be 9 (1+3+5), the seventh would be 17 (3+5+9), etc.
Name your function fib3, and make sure to use recursion.
The lines below will test your code.
If your function is correct, they will print 1, 3, 17, and 57.
print(fib3(3))
print(fib3(4))
print(fib3(7))
print(fib3(9))
This is the code until now:
def fib3(n):
if n <= 1:
return n
else:
return(fib3(n-1) + fib3(n-2) + fib3(n-3))
But the results are: 1, 2, 11, 37
Can you help me please to correct it?
The same thing other people are saying
As others have noted, you have to return 1 when n <= 3
def fib3 (n):
if n <= 3:
return 1
else:
return fib3(n - 1) + fib3(n - 2) + fib3(n - 3)
print(fib3(3)) # 1
print(fib3(4)) # 3
print(fib3(7)) # 17
print(fib3(9)) # 57
... but you can do better than that
But that definition of fib3 is junk. It does an insane amount of computation duplication. For example, fib3(40) takes over 30 minutes to compute due to O(n3) complexity
Consider an approach that uses an auxiliary loop with state variables – The O(n) complexity allows it to compute the same result in less than a millisecond.
def fib3 (n):
def aux (n,a,b,c):
if n == 1:
return a
else:
return aux(n-1,b,c,a+b+c)
return aux(n,1,1,1)
print(fib3(3)) # 1
print(fib3(4)) # 3
print(fib3(7)) # 17
print(fib3(9)) # 57
print(fib3(40)) # 9129195487
Fibonacci as a generic program: fibx
We can make generic the entire process of generating fibonacci sequences, but first we have to address something with your fib3 function. In general, Fibonacci numbers have a 0th term - ie, fib(0) == 0, fib(1) == 1. In your function, it looks like the first number is fib3(1), where fib3(0) would produce an undefined result.
Below, I'm going to introduce fibx which can take any binary operator and any seed values and create any fibonacci sequence we can imagine
from functools import reduce
def fibx (op, seed, n):
[x,*xs] = seed
if n == 0:
return x
else:
return fibx(op, xs + [reduce(op, xs, x)], n - 1)
Now we can implement standard fibonacci using fibx with the add (+) operator and seed values 0,1
from operator import add
def fib (n):
return fibx(add, [0,1], n)
print(fib(0)) # 0
print(fib(1)) # 1
print(fib(2)) # 1
print(fib(3)) # 2
print(fib(4)) # 3
print(fib(5)) # 5
Implementing fib3 using fibx
We can use the same fibx with the add operator to implement your fib3 function, but because of your 1-based index, notice I'm offsetting n by 1 to get the correct output
from operator import add
def fib3 (n):
return fibx(add, [1,1,1], n-1)
print(fib3(3)) # 1
print(fib3(4)) # 3
print(fib3(7)) # 17
print(fib3(9)) # 57
I'd recommend you start with a 0-based index tho. This means 0-based index fib3(2) is actually equal to your 1-based index of fib3(3)
from operator import add
def fib3 (n):
return fibx(add, [1,1,1], n)
print(fib3(2)) # 1
print(fib3(3)) # 3
print(fib3(6)) # 17
print(fib3(8)) # 57
Any imaginable sequence using fibx
And of course you can make any other sequence you can imagine. Here we make weirdfib that uses multiplication (*) instead of addition (+) to combine terms and has a starting seed of [1,2,3]
from operator import mul
def weirdfib (n):
return fibx(mul, [1,2,3], n)
print(weirdfib(0)) # 1
print(weirdfib(1)) # 2
print(weirdfib(2)) # 3
print(weirdfib(3)) # 6
print(weirdfib(4)) # 36
print(weirdfib(5)) # 648
print(weirdfib(6)) # 139968
Your problem description tells you why:
The sequence will start with three 1s
Your solution, however only returns 1 for n == 1 or lower:
if n <= 1:
return n
This means that for n == 2 (which should still return 1), you'd instead return fib3(2-1) + fib3(2-2) + fib3(2-3), or fib3(1) + fib3(0) + fib(-1), which thanks to the above test, then bottoms out to produce 1 + 0 + -1 == 0.
For n == 3, you'd return fib3(2) + fib3(1) + fib3(0); we worked out above that fib3(2) is 0, so the end result is 0 + 1 + 0 is the 1 you observed.
Finally, the 4th fib3 number (n == 4), does not return 3, but fib3(3) + fib3(2) + fib3(1) == 1 + 0 + 1 == 2.
Change that first test return 1 for n <= 3, to fix those first 3 values in the series:
def fib3(n):
if n <= 3:
return 1
else:
return fib3(n-1) + fib3(n-2) + fib3(n-3)
Now the code passes the given tests:
>>> def fib3(n):
... if n <= 3:
... return 1
... else:
... return fib3(n-1) + fib3(n-2) + fib3(n-3)
...
>>> print(fib3(3))
1
>>> print(fib3(4))
3
>>> print(fib3(7))
17
>>> print(fib3(9))
57
If n <= 1, the situation is a little more complex than just return n.
Consider the case of n = 4: your recursive call will be fib(3), fib(2), and fib(1).
The lattermost returns 1 immediately, which is what you want. However, the two recursive calls do some weird things. fib(2) recurses into fib(1), fib(0), and fib(-1), the return values for which basically hand back a big fat 0. fib(3) recurses into fib(2) (which we saw is 0), fib(1) (which works, and is 1), and fib(0) (which is also 0).
Hence, you get the 1 from the very beginning, and the 1 from the recursed fib(1) component of fib(3). There's your 2!
Basically, you want to make sure your base case can't return a negative number. Fix that (return either 1 or 0), and you should be good. As Martijn Pieters mentioned, you can also make your base case n <= 3 and it should achieve the same effect.
Let me contribute with perhaps the most optimal "pythonic" answer.
The main point is to avoid recursive function calls to optimise the efficiency of the code. Pythonic way of thinking would involve the following compact code, which is an iterative creation of the Fibonacci sequence of n numbers, including the seed numbers [1, 1, 1].
def fibonacci_sequence(n):
x = [1, 1, 1]
[x.append(x[-1] + x[-2] + x[-3]) for i in range(n - len(x))]
return x
import time
n = int(raw_input("Enter the size of Fibonacci-3 sequence: "))
start_time = time.time()
print fibonacci_sequence(n)
print "The time to compute the Fibonacci-3 sequence is: %s" % (time.time() - start_time)
Related
Is there a Way in Python to have a for loop which cycle only on multiples of a given number that are not multiples of any number lower than given number?
I mean something like this:
if given_number = 13
the for loop is going to cycle only on [13 * 13, 13 * 17, 13 * 19, 13 * 23, 13*29, 13*31, 13*39, ........]
I came across this kind of problem working on this function:
def get_primes_lower_n(n: int) -> List[int]:
"""
n: int
the given input number
returns: List[int]
all primes number lower than given input number
raises:
ValueError: the given input is an integer < 2
TypeError: the given input is not an integer
"""
if not isinstance(n, int):
raise TypeError("an integer is required")
if n < 2:
raise ValueError("an integer > 1 is required")
primes = np.ones(n + 1, dtype=bool) # bool(1) = True
primes[:2] = False
primes[4:: 2] = False
for i in range(3, isqrt(n) + 1, 2):
if primes[i]:
primes[i ** 2:: 2 * i] = False
return np.where(primes == True)[0]
if n is something like 9 * 10 ** 9 the algorithm is going to explode. For any value of I primes[i ** 2:: 2 * i] = False is going to take more or less 52 seconds. Let's think of I = 7; primes[i ** 2:: 2 * i] = False
is going to set to False all values in positions multiples of 21 and 35 that are already set to False.
As the value of I increases, I expect the time of execution of this operation primes[i ** 2:: 2 * i] = False to take less time (less values need to be set), but instead it increases exponentially. Why?
To answer your first question:
Is there a Way in python to have a for loop which cycle only on multiples of a given number that are not multiples of any number lower than given number?
Yes there is, but not efficient enough (unless you find a faster implementation).
Let n be the number we are looking at.
The numbers that are not multiples of any number lower than n are exactly the numbers left from the sieve when ran up to n. Therefore, these numbers are already present in the array, they are the True values with index greater than n. Unfortunately, as these are stored by index, finding them is expensive and finally makes the code go slower, as the collisions from the original algorithm are so rare. Still, here is a possible implementation in the for loop.
for i in range(3, isqrt(n) + 1, 2):
primes[i*(np.nonzero(primes[i:n//i])[0]+i)] = False
# [i:n//i] is to bound the search from i to the last number such
# that i*(n//i) < n.
Here is an equivalent code without the bool array:
def get_primes_lower_n(n: int) -> list[int]:
primes = np.arange(3, n + 1, 2) # only odd numbers over 3
val = 0
idx = -1
while val <= isqrt(n)+1:
idx += 1
val = primes[idx]
primes = np.setdiff1d(primes, val*primes[idx:idx+bisect.bisect_left(primes[idx:], n//val+1)])
return np.insert(primes, 0, 2)
As a conclusion, it is worth it to set the same values multiple times rather than use an exact approch that is slower.
Sorry for the lack of working solution but i hope this can help you in some way. If you find an interesting algorithm, feel free to let me know!
I want to make a function where given a number like 7 I want to factorise the number by as many 3s and 2s. If left with a remainder then return -1.
Note: Through further examples it seems any number can be made up of the addition of multiples of 3s and 2s so -1 for remainder not needed. Goal is to get as many multiples of 3 before having to add multiples of 2 to factorise completely
For example given the number 11 I want the function to return 3:3 and 2:1 as 3 fits into 11 3 times and 2 once ie. 3+2+2=7, 3+3+3+2=11, 3+3+3+2+2=13. The preference should be being able to fit as many 3s first.
This is part of a wider problem:
from collections import Counter
#Choose two packages of the same weight
#Choose three packages of the same weight
#Minimum number of trips to complete all the deliveries else return -1
def getMinimumTrips(weights):
weights_counted = Counter(weights)
minimum_trips = 0
print(weights_counted)
for i in weights_counted:
if weights_counted[i]==1:
return -1
elif weights_counted[i]%3==0:
minimum_trips += (weights_counted[i]//3)
elif weights_counted[i]%2==0:
minimum_trips += (weights_counted[i]//2)
return minimum_trips
print(getMinimumTrips([2, 4, 6, 6, 4, 2, 4]))
Possible solution:
#Looking at inputs that are not a multiple of 3 or 2 eg, 5, 7, 11, 13
def get_components(n):
f3 = 0
f2 = 0
if n%3==1:
f3 = (n//3)-1
f2 = 2
elif n%3==2:
f3 = (n//3)
f2=1
return f"3:{f3}, 2:{f2}"
If we are given some integer value x we have 3 different cases:
x == 3 * n, solution: return 3 n times. The easiest case.
x == 3 * n + 1, solution: return 3 n - 1 times, then return 2 2 times, Note that we can put 3 * n + 1 == 3 * (n - 1) + 2 + 2
x == 3 * n + 2, solution: return 3 n times, then return 2.
As one can see in cases #1 and #3 solutions ever exist; in case #2 there's no solution for x = 1 (we can't return 3 -1 times). So far so good if x <= 1 we return -1 (no solutions), otherwise we perform integer division // and obtain n, then find remainder % and get the case (remainder 0 stands for case #1, 1 for case #2, 2 for case #3). Since the problem looks like a homework let me leave the rest (i.e. exact code) for you to implement.
This will return 0 if you can completely factorise the number, or -1 if 1 is remaining:
return -(i % 3 % 2)
If this helps?
Try this method using math.floor()
import math
def get_components(n: int) -> str:
q3 = math.floor(n / 3)
q2 = math.floor(q3 / 2)
if not (q3 and q2):
return '-1' # returning '-1' as a string here for consistency
return f'3:{q3}, 2:{q2}'
I'm studing recursive function and i faced question of
"Print sum of 1 to n with no 'for' or 'while' "
ex ) n = 10
answer =
55
n = 100
answer = 5050
so i coded
import sys
sys.setrecursionlimit(1000000)
sum = 0
def count(n):
global sum
sum += n
if n!=0:
count(n-1)
count(n = int(input()))
print(sum)
I know it's not good way to get right answer, but there was a solution
n=int(input())
def f(x) :
if x==1 :
return 1
else :
return ((x+1)//2)*((x+1)//2)+f(x//2)*2
print(f(n))
and it works super well , but i really don't know how can human think that logic and i have no idea how it works.
Can you guys explain how does it works?
Even if i'm looking that formula but i don't know why he(or she) used like that
And i wonder there is another solution too (I think it's reall important to me)
I'm really noob of python and code so i need you guys help, thank you for watching this
Here is a recursive solution.
def rsum(n):
if n == 1: # BASE CASE
return 1
else: # RECURSIVE CASE
return n + rsum(n-1)
You can also use range and sum to do so.
n = 100
sum_1_to_n = sum(range(n+1))
you can try this:
def f(n):
if n == 1:
return 1
return n + f(n - 1)
print(f(10))
this function basically goes from n to 1 and each time it adds the current n, in the end, it returns the sum of n + n - 1 + ... + 1
In order to get at a recursive solution, you have to (re)define your problems in terms of finding the answer based on the result of a smaller version of the same problem.
In this case you can think of the result sumUpTo(n) as adding n to the result of sumUpTo(n-1). In other words: sumUpTo(n) = n + sumUpTo(n-1).
This only leaves the problem of finding a value of n for which you know the answer without relying on your sumUpTo function. For example sumUpTo(0) = 0. That is called your base condition.
Translating this to Python code, you get:
def sumUpTo(n): return 0 if n==0 else n + sumUpTo(n-1)
Recursive solutions are often very elegant but require a different way of approaching problems. All recursive solutions can be converted to non-recursive (aka iterative) and are generally slower than their iterative counterpart.
The second solution is based on the formula ∑1..n = n*(n+1)/2. To understand this formula, take a number (let's say 7) and pair up the sequence up to that number in increasing order with the same sequence in decreasing order, then add up each pair:
1 2 3 4 5 6 7 = 28
7 6 5 4 3 2 1 = 28
-- -- -- -- -- -- -- --
8 8 8 8 8 8 8 = 56
Every pair will add up to n+1 (8 in this case) and you have n (7) of those pairs. If you add them all up you get n*(n+1) = 56 which correspond to adding the sequence twice. So the sum of the sequence is half of that total n*(n+1)/2 = 28.
The recursion in the second solution reduces the number of iterations but is a bit artificial as it serves only to compensate for the error introduced by propagating the integer division by 2 to each term instead of doing it on the result of n*(n+1). Obviously n//2 * (n+1)//2 isn't the same as n*(n+1)//2 since one of the terms will lose its remainder before the multiplication takes place. But given that the formula to obtain the result mathematically is part of the solution doing more than 1 iteration is pointless.
There are 2 ways to find the answer
1. Recursion
def sum(n):
if n == 1:
return 1
if n <= 0:
return 0
else:
return n + sum(n-1)
print(sum(100))
This is a simple recursion code snippet when you try to apply the recurrent function
F_n = n + F_(n-1) to find the answer
2. Formula
Let S = 1 + 2 + 3 + ... + n
Then let's do something like this
S = 1 + 2 + 3 + ... + n
S = n + (n - 1) + (n - 2) + ... + 1
Let's combine them and we get
2S = (n + 1) + (n + 1) + ... + (n + 1) - n times
From that you get
S = ((n + 1) * n) / 2
So for n = 100, you get
S = 101 * 100 / 2 = 5050
So in python, you will get something like
sum = lambda n: ( (n + 1) * n) / 2
print(sum(100))
Hey I am trying to get a Fibonacci sequence to output with a single variable in the mix. normally if I was using 2 variables I would have it set up like this:
nmbr1 = nmbr2 = 1
while nmbr1 < 100:
nmbr1, nmbr2 = nmbr1 + nmbr2, nmbr1
print (nmbr1)
but how would I get it complete the sequence with only one variable in python?
Since nobody mentioned what sort of object the variable should be, here's using a list ;-)
x = [1, 1]
while x[0] < 100:
x = x[1], sum(x)
print(x[0])
1
2
3
5
8
13
21
34
55
89
144
If you really want to be sneaky, you can use the closed form solution for the Fibonacci series by approximation with the golden ratio.
def fib(n):
return int((((1 + 5 ** .5) / 2) ** n) / (5 ** .5) + .5)
f = c = 1
while f < 100:
c += 1
f = fib(c)
print(f)
1
2
3
5
8
13
21
34
55
89
144
This only uses one variable - n - and it calculates F[n] in constant time. Run a loop and keep calling fib successively.
def fib(n):
if n <= 2: return 1
return fib(n-1) + fib(n-2)
print fib(12) # the 12th fibinocci number
maybe ... it works a bit different then yours and it will fall apart with big numbers probably
This is an interesting solution. The memoization component is courtesy of Efficient calculation of Fibonacci series.
import functools
#functools.lru_cache(None)
def fib(n):
if n < 2:
return n
return fib(n-1) + fib(n-2)
def fib_yield(n):
for i in range(n):
yield fib(i)
list(fib_yield(10)) # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
yes definitely agree with #joran-beasley
fastest and advanced technique for this is Memoization technique, though it is complicated. Memoization avoids computing already computed values by storing them, here we can store it in the dictionary with its positions as keys.
I learnt this from a very old answer in SO https://stackoverflow.com/a/18172463/5334188
I have the following code for Project Euler Problem 12. However, it takes a very long time to execute. Does anyone have any suggestions for speeding it up?
n = input("Enter number: ")
def genfact(n):
t = []
for i in xrange(1, n+1):
if n%i == 0:
t.append(i)
return t
print "Numbers of divisors: ", len(genfact(n))
print
m = input("Enter the number of triangle numbers to check: ")
print
for i in xrange (2, m+2):
a = sum(xrange(i))
b = len(genfact(a))
if b > 500:
print a
For n, I enter an arbitrary number such as 6 just to check whether it indeed returns the length of the list of the number of factors.
For m, I enter entered 80 000 000
It works relatively quickly for small numbers. If I enter b > 50 ; it returns 28 for a, which is correct.
My answer here isn't pretty or elegant, it is still brute force. But, it simplifies the problem space a little and terminates successfully in less than 10 seconds.
Getting factors of n:
Like #usethedeathstar mentioned, it is possible to test for factors only up to n/2. However, we can do better by testing only up to the square root of n:
let n = 36
=> factors(n) : (1x36, 2x18, 3x12, 4x9, 6x6, 9x4, 12x3, 18x2, 36x1)
As you can see, it loops around after 6 (the square root of 36). We also don't need to explicitly return the factors, just find out how many there are... so just count them off with a generator inside of sum():
import math
def get_factors(n):
return sum(2 for i in range(1, round(math.sqrt(n)+1)) if not n % i)
Testing the triangular numbers
I have used a generator function to yield the triangular numbers:
def generate_triangles(limit):
l = 1
while l <= limit:
yield sum(range(l + 1))
l += 1
And finally, start testing:
def test_triangles():
triangles = generate_triangles(100000)
for i in triangles:
if get_factors(i) > 499:
return i
Running this with the profiler, it completes in less than 10 seconds:
$ python3 -m cProfile euler12.py
361986 function calls in 8.006 seconds
The BIGGEST time saving here is get_factors(n) testing only up to the square root of n - this makes it heeeaps quicker and you save heaps of memory overhead by not generating a list of factors.
As I said, it still isn't pretty - I am sure there are more elegant solutions. But, it fits the bill of being faster :)
I got my answer to run in 1.8 seconds with Python.
import time
from math import sqrt
def count_divisors(n):
d = {}
count = 1
while n % 2 == 0:
n = n / 2
try:
d[2] += 1
except KeyError:
d[2] = 1
for i in range(3, int(sqrt(n+1)), 2):
while n % i == 0 and i != n:
n = n / i
try:
d[i] += 1
except KeyError:
d[i] = 1
d[n] = 1
for _,v in d.items():
count = count * (v + 1)
return count
def tri_number(num):
next = 1 + int(sqrt(1+(8 * num)))
return num + (next/2)
def main():
i = 1
while count_divisors(i) < 500:
i = tri_number(i)
return i
start = time.time()
answer = main()
elapsed = (time.time() - start)
print("result %s returned in %s seconds." % (answer, elapsed))
Here is the output showing the timedelta and correct answer:
$ python ./project012.py
result 76576500 returned in 1.82238006592 seconds.
Factoring
For counting the divisors, I start by initializing an empty dictionary and a counter. For each factor found, I create key of d[factor] with value of 1 if it does not exist, otherwise, I increment the value d[factor].
For example, if we counted the factors 100, we would see d = {25: 1, 2: 2}
The first while loop, I factor out all 2's, dividing n by 2 each time. Next, I begin factoring at 3, skipping two each time (since we factored all even numbers already), and stopping once I get to the square root of n+1.
We stop at the square_root of n because if there's a pair of factors with one of the numbers bigger than square_root of n, the other of the pair has to be less than 10. If the smaller one doesn't exist, there is no matching larger factor.
https://math.stackexchange.com/questions/1343171/why-only-square-root-approach-to-check-number-is-prime
while n % 2 == 0:
n = n / 2
try:
d[2] += 1
except KeyError:
d[2] = 1
for i in range(3, int(sqrt(n+1)), 2):
while n % i == 0 and i != n:
n = n / i
try:
d[i] += 1
except KeyError:
d[i] = 1
d[n] = 1
Now that I have gotten each factor, and added it to the dictionary, we have to add the last factor (which is just n).
Counting Divisors
Now that the dictionary is complete, we loop through each of the items, and apply the following formula: d(n)=(a+1)(b+1)(c+1)...
https://www.wikihow.com/Determine-the-Number-of-Divisors-of-an-Integer
All this formula means is taking all of the counts of each factor, adding 1, then multiplying them together. Take 100 for example, which has factors 25, 2, and 2. We would calculate d(n)=(a+1)(b+1) = (1+1)(2+1) = (2)(3) = 6 total divisors
for _,v in d.items():
count = count * (v + 1)
return count
Calculate Triangle Numbers
Now, taking a look at tri_number(), you can see that I opted to calculate the next triangle number in a sequence without manually adding each whole number together (saving me millions of operations). Instead I used T(n) = n (n+1) / 2
http://www.maths.surrey.ac.uk/hosted-sites/R.Knott/runsums/triNbProof.html
We are providing a whole number to the function as an argument, so we need to solve for n, which is going to be the whole number to add next. Once we have the next number (n), we simply add that single number to num and return
S=n(n+1)2
S=n2+n2
2S=n2+n
n2+n−2S=0
At this point, we use the quadratic formula for : ax2+bx+c=0.
n=−b±√b2−4ac / 2a
n=−1±√1−4(1)(−2S) / 2
n=−1±√1+8S / 2
https://socratic.org/questions/how-do-you-solve-for-n-in-s-n-n-1-2
So all tri_number() does is evaluate n=1+√1+8S / 2 (we ignore the negative equation here). The answer that is returned is the next triangle number in the sequence.
def tri_number(num):
next = 1 + int(sqrt(1+(8 * num)))
return num + (next/2)
Main Loop
Finally, we can look at main(). We start at whole number 1. We count the divisor of 1. If it is less than 500, we get the next triangle number, then try again and again until we get a number with > 500 divisors.
def main():
i = 1
while count_divisors(i) < 500:
i = tri_number(i)
return i
I am sure there are additional ways to optimize but I am not smart enough to understand those ways. If you find any better ways to optimize python, let me know! I originally solved project 12 in Golang, and that run in 25 milliseconds!
$ go run project012.go
76576500
2018/07/12 01:56:31 TIME: main() took 23.581558ms
one of the hints i can give is
def genfact(n):
t = []
for i in xrange(1, n+1):
if n%i == 0:
t.append(i)
return t
change that to
def genfact(n):
t=[]
for i in xrange(1,numpy.sqrt(n)+1):
if(n%i==0):
t.append(i)
t.apend(n/i)
since if a is a divisor than so is b=n/a, since a*b=a*n/b=n, That should help a part already (not sure if in your case a square is possible, but if so, add another case to exclude adding the same number twice)
You could devise a recursive thing too, (like if it is something like for 28, you get 1,28,2,14 and at the moment you are at knowing 14, you put in something to actually remember the divisors of 14 (memoize), than check if they are alraedy in the list, and if not, add them to the list, together with 28/d for each of the divisors of 14, and at the end just take out the duplicates
If you think my first answer is still not fast enough, ask for more, and i will check how it would be done to solve it faster with some more tricks (could probably make use of erastothenes sieve or so too, and some other tricks could be thought up as well if you would wish to really blow up the problem to huge proportions, like to check the first one with over 10k divisors or so)
while True:
c=0
n=1
m=1
for i in range(1,n+1):
if n%i==0:
c=c+1
m=m+1
n=m*(m+1)/2
if c>500:
break
print n
this is not my code but it is so optimized.
source: http://code.jasonbhill.com/sage/project-euler-problem-12/
import time
def num_divisors(n):
if n % 2 == 0: n = n / 2
divisors = 1
count = 0
while n % 2 == 0:
count += 1
n = n / 2
divisors = divisors * (count + 1)
p = 3
while n != 1:
count = 0
while n % p == 0:
count += 1
n = n / p
divisors = divisors * (count + 1)
p += 2
return divisors
def find_triangular_index(factor_limit):
n = 1
lnum, rnum = num_divisors(n), num_divisors(n + 1)
while lnum * rnum < 500:
n += 1
lnum, rnum = rnum, num_divisors(n + 1)
return n
start = time.time()
index = find_triangular_index(500)
triangle = (index * (index + 1)) / 2
elapsed = (time.time() - start)
print("result %s returned in %s seconds." % (triangle, elapsed))