I am trying to implement the total sum of N whole numbers in Fibonacci
def fibo(n):
if n<2:
return 1
else:
res = fibo(n-1) + fibo(n-2)
sum = sum + res
return res, sum
n=7
sum = 0
for i in range(1, n):
print(fibo(i))
print("Suma", sum)
#example: if n=7 then print : 1,1,2,3,5,8,13 and sum is 32
The error I have is, when I put sum = sum + res
Doesnt print & run the program
Currently, how could you implement the total sum?
You simply need to calculate sum in the for loop, not in the fibo(n).
Here take a look:
def fibo(n):
if n<2:
return 1
else:
res = fibo(n-1) + fibo(n-2)
return res
n=7
sum = 0
for i in range(0, n):
r = fibo(i)
sum += r
print(r)
print("Suma", sum)
I used r in order to call fibo once in each loop.
Let me first point out that the sum of the first 7 terms of the Fibonacci sequence is not 32. That sum is 33. Now to the problem. Here is how I would solve the problem. I would first define the function that calculates the n th term of the Fibonacci sequence as follows:
def fibo(n):
if n in [1,2]:
return 1
else:
res = fibo(n-1) + fibo(n-2)
return res
Then I would define a function to calculate the sum of the first n terms of the Fibonacci sequence as follows.
def sum_fibo(n):
res = [fibo(i) for i in range(1, n+1)]
print(res)
return sum(res)
So if I do
[In] sum_fibo(7)
I get
[1, 1, 2, 3, 5, 8, 13]
out >>> 33
NOTE: In defining the functions above, I have assumed that the input of the function is always going to be a positive integer though the Fibonacci can be extended to cover all real and complex numbers as shown on this wiki page.
actually i don't think this needs to be that complicated the fibonacci sequence is very interesting in a maltitude of ways for example, if you want the sum up the 7th fibonacci number, then have checked what the 9th fibonacci number - 1 is? Now how do we find the n'th fibonacci number?
p = (1+5**.5)/2
q = (1-5**.5)/2
def fibo(n):
return 1/5**.5*(p**n-q**n)
and now we can can find the sum up to any number in one calculation! for example for 7
fibo(9)- 1
output
33
and what is the actual answer
1+1+2+3+5+8+13=33
summa summarum: the fibonachi number that is two places further down the sequence minus 1 is the sum of the fibonachi numbers up to the number
def sumOfNFibonacciNumbers(n):
# Write your code here
i = 1
sum = 2
fib_list = [0, 1, 1]
if n == 1:
return 0
if n == 2:
return 1
if n == 3:
return 2
for x in range(1,n-2):
m = fib_list[-1] + fib_list[-2]
fib_list.append(m)
sum = sum + m
return sum
result = sumOfNFibonacciNumbers(10)
print(result)
Made some modifications to your code:
def fibo(n):
print(1)
counter = 1
old_num = 0
new_num = 1
sum_fib = 1
while counter < n:
fib = old_num + new_num
print(fib)
if counter < n:
old_num = new_num
new_num = fib
sum_fib = sum_fib + fib
counter = counter + 1
print('sum:' + str(sum_fib))
#fibo(5)
First of all, the line sum = sum + res makes no sense because you never defined sum in the first place.
So, your function should look like
def fibo(n):
if n<2:
return 1
else:
return fibo(n-1) + fibo(n-2)
Second, you can get the sum by simply
sum_ = 0
for i in range(0, n):
sum_ += fibo(i)
Or maybe
sum_ = sum(fibo(i) for i in range(0, n))
Notice that the latter would only work if you have not overridden the built-in function named sum
You are referring the variable sum before assignment.
You may want to use the variable sum inside the for loop and assign the fibo to it.
def fibo(n):
if n<2:
return 1
else:
return fibo(n-1) + fibo(n-2)
n=7
sum = 0
for i in range(1, n):
sum += fibo(i)
print(fibo(i))
print("suma", sum)
Considering the start of the Fibonacci series with 1 rather than 0.
def fib(no_of_elements):
elements, start = [], 1
while start <= no_of_elements:
if start in [1, 2]:
elements.append(1)
elif start >= 3:
elements.append(elements[start-2]+elements[start-3])
start += 1
return elements, sum(elements)
print(fib(8))
Output:
([1, 1, 2, 3, 5, 8, 13, 21], 54)
Related
I am trying to add all even Fibonacci numbers up to 4000000. I have successfully outputted all Fibonacci numbers up to 4000000, but adding all the even ones is becoming a problem for me. So far this is what I tried:
fibonacci = [1, 2]
i = 0
while fibonacci[-1] < 4000000:
fib = fibonacci[-1] + fibonacci[-2]
fibonacci.append(fib)
i += 1
del fibonacci[-1]
result = 0
for x in fibonacci:
if fibonacci[x] % 2 == 0:
result += fibonacci[x]
print(result)
It outputs an error:
IndexError: list index out of range
In the lines:
for x in fibonacci:
if fibonacci[x] % 2 == 0:
result += fibonacci[x]
x is actually the Fibonacci number itself, not an index, and is guaranteed to be outside of the bounds of the fibonacci list. If the code was for x in range(len(fibonacci)):, this would yield the indexes as x.
Change it to:
for x in fibonacci:
if x % 2 == 0:
result += x
or better yet, use a list comprehension:
result = sum(x for x in fibonacci if x % 2 == 0)
print(result)
Furthermore, instead of building an entire list, you could accumulate the sum on the spot as you generate the Fibonacci numbers, which is much more memory-efficient:
def even_fib_sum(n):
total = 0
a = 0
b = 1
while a < n:
if a % 2 == 0:
total += a
a, b = a + b, a
return total
if __name__ == "__main__":
print(even_fib_sum(55))
Or, even better, you can use a generator and drop even, since fib is more generally reusable:
def fib(n):
a = 0
b = 1
while a < n:
yield a
a, b = a + b, a
if __name__ == "__main__":
print(sum(x for x in fib(4000000) if x % 2 == 0))
Note that the Fibonacci series usually begins with 0, 1, 1, 2, 3, 5... rather than 1, 2, 3, 5... but you can adjust this as necessary, along with whether you want to iterate inclusive of n or not.
A small compilation of previous answers
fibonacci = [0, 1]
while fibonacci[-1] + fibonacci[-2] < 4000000:
fibonacci.append(fibonacci[-1] + fibonacci[-2])
print(sum(x for x in fibonacci if x % 2 == 0))
That's how I wrote as a beginner.
#By considering the terms in the Fibonacci sequence whose values do
#not exceed four million,
#find the sum of the even-valued terms.
cache = {}
def fib(n):
if n < 3:
return 1
elif n in cache:
return cache[n]
else:
value = fib(n - 1) + fib(n - 2)
cache[n] = value
return value
tot = 0
for n in range(1, 34):
if fib(n) % 2 == 0:
tot += fib(n)
print(n, ':', fib(n))
print(tot)
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
Written a program to find the find the Strong number
A number is considered to be a Strong number if sum of the factorial of its digits is equal to the number itself.
145 is a Strong number as 1! + 4! + 5! = 145.
Need to accept a list, find the Strong Number among the list and return a list of same
Ive tried :
def factorial(number):
if number == 0 or number == 1:
return 1
else :
return number * factorial(number - 1)
def find_strong_numbers(num_list):
sum = 0
ret_list = []
for i in num_list :
sum = 0
lst = list(map(int,list(str(i)))) #Converting the number into a list of numbers
for j in lst :
sum += factorial(j)
if sum == i :
ret_list.append(i)
return ret_list
num_list=[145,375,100,2,10]
strong_num_list=find_strong_numbers(num_list)
print(strong_num_list)
In the above example, I have created a list of the digits of the number and found its factorial.
But,
def factorial(number):
if number == 0 or number == 1:
return 1
else :
return number * factorial(number - 1)
def find_strong_numbers(num_list):
sum = 0
ret_list = []
for i in num_list :
sum = 0
lst = list(str(i)) #A List of Strings of the digits
for j in lst :
sum += factorial(int(j))
if sum == i :
ret_list.append(i)
return ret_list
num_list=[145,375,100,2,10]
strong_num_list=find_strong_numbers(num_list)
print(strong_num_list)
Ive created a list of Strings of Digits in the number
Converted the string to number when calling the factorial function.
This seems to be efficient for me as I need not to convert it into a map and then to int(less conversion)
Is this correct, is this efficient than the previous one or is there any far better optimised Code than this to find Strong Number.
You can simply memoize the factorial function to speed up the processing
from functools import lru_cache
#lru_cache(maxsize=128)
def factorial(number):
if number <= 1:
return 1
else:
return number * factorial(number - 1)
Also, you can use a generator to get the next digit like this
def get_next_digit(num):
while num:
yield num % 10
num //= 10
print(sum(factorial(digit) for digit in get_next_digit(145)))
This avoids creating an intermittent list of strings.
PS: These are minor optimisations which may not greatly improve the performance of the program.
Overall Code
from functools import lru_cache
#lru_cache(maxsize=128)
def factorial(number):
if number <= 1:
return 1
else:
return number * factorial(number - 1)
def get_next_digit(num):
while num:
yield num % 10
num //= 10
def is_strong_number(num):
return sum(factorial(digit) for digit in get_next_digit(num)) == num
def find_strong_numbers(num_list):
return [num for num in num_list if is_strong_number(num)]
num_list = [145, 375, 100, 2, 10]
print(find_strong_numbers(num_list))
Since you're only using factorials of 0..9, there's no need to have a function to compute them, let alone a recursive one. You can just hardcode all 10 values:
facts = {'0': 1, '1': 1, '2': 2, '3': 6, '4': 24, '5': 120, '6': 720, '7': 5040, '8': 40320, '9': 362880}
and then simply use:
def is_strong(n):
return sum(facts[s] for s in str(n)) == n
You can squeeze a bit more cycles of out this by avoiding a string conversion:
facts2 = [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880]
def is_strong2(n):
s, k = 0, n
while k:
s += facts2[k % 10]
k //= 10
return s == n
...but given the fact that it's proven there are no such numbers beside 1, 2, 145, 40585, the whole enterprise looks a bit pointless ;)
Another version, using builtin math.factorial (doc):
from math import factorial
def is_strong_number(num):
return num == sum(factorial(int(c)) for c in str(num))
num_list=[145,375,100,2,10]
strong_num_list = [num for num in num_list if is_strong_number(num)]
print(strong_num_list)
Prints:
[145, 2]
others have already suggested improvements in their answers,
just for the sake of demonstrating a more empirical approach to runtime benchmarking:
you can use timeit to compare the runtime of different functions.
I added both of yours, and also a version that doesn't do the string<->int casting at all.
import timeit
def factorial(number):
if number == 0 or number == 1:
return 1
else:
return number * factorial(number - 1)
def find_strong_numbers_with_map(num_list):
sum = 0
ret_list = []
for i in num_list:
sum = 0
lst = list(map(int, list(str(i)))) # Converting the number into a list of numbers
for j in lst:
sum += factorial(j)
if sum == i:
ret_list.append(i)
return ret_list
def find_strong_numbers_cast_on_call(num_list):
sum = 0
ret_list = []
for i in num_list:
sum = 0
lst = list(str(i)) # A List of Strings of the digits
for j in lst:
sum += factorial(int(j))
if sum == i:
ret_list.append(i)
return ret_list
def find_strong_numbers_by_div_mod(num_list):
sum = 0
ret_list = []
for i in num_list:
sum = 0
while i > 0:
j = i % 10 # get the value of the last digit
sum += factorial(int(j))
i = i // 10 # "cut" the last digit from i
if sum == i:
ret_list.append(i)
return ret_list
num_list = [*range(1, 1000)]
print(timeit.timeit(lambda: find_strong_numbers_with_map(num_list), number=10 ** 3))
print(timeit.timeit(lambda: find_strong_numbers_cast_on_call(num_list), number=10 ** 3))
print(timeit.timeit(lambda: find_strong_numbers_by_div_mod(num_list), number=10 ** 3))
results on my laptop are:
2.4222552359969995
2.114583875001699
1.8628507399989758
There are several things you can do.
The first thing that comes to mind is making the factorial function iterative, instead of recursive:
def factorial(number):
if number == 0 or number == 1:
return 1
result = 1
for i in range(number + 1):
result *= i
return result
The second one would be to precompute all factorials for each digit, since there is a limited amount of them:
def get_factorials():
result = [1, 1]
value = 1
for i in range(2, 10):
value *= i
result.append(value)
return result
Then, instead of calling factorial each time, you could just do:
factorials = get_factorials()
lst = list(str(i))
for j in lst :
sum += factorials[int(j)]
Your result function could then be as simple as:
def is_strong_number(num):
return num == sum(map(lambda x: factorials[int(x)], str(num))
def find_strong_numbers(nums):
factorials = get_factorials()
return [num for num in nums if is_strong_number(num)]
Edit: thanks khelwood, fixed :)
Hi I'm fairly new to python and trying to create a Fibonacci calculator function that prints all values up to a given number, if the number entered is not in the sequence then it adds the next Fibonacci number to the list. For example, if 10 is entered it should return [0, 1, 1, 2, 3, 5, 8, 13]. The function has to be recursive. Here is my current code:
def fibonacci(n):
n = int(n)
# The nested sub_fib function computes the Fibonacci sequence
def sub_fib(n):
if n < 2:
return n
else:
return (sub_fib(n-1) + sub_fib(n-2))
#This aspect of the main fib function applies the condition if the number
# input is not in the sequence then it returns the next value up
fib_seq= [sub_fib(i) for i in range(0,n) if sub_fib(i)<=n]
if fib_seq[-1] < n:
fib_seq.append(fib_seq[-1] + fib_seq[-2])
return fib_seq
else:
return fib_seq
print(fibonacci(input("Input a number to print sequence up to: ")))
I've managed to get it to work but it is incredibly slow (I assume due to the recursion) is there anyway I can speed it up without massively changing the program?
The two main reasons why your program is slow:
you calculate each Fibonacci number separately, you do not reuse the effort you have invested in finding the previous number;
you calculate the first n Fibonacci numbers, but from the moment the condition fails, you can stop.
You can change the program to still be recursive, but reuse the work to compute the previous number, and stop from the moment you have constructed the list.
You simply have to use the following function:
def fibon(a,b,n,result):
c = a+b
result.append(c)
if c < n:
fibon(b,c,n,result)
return result
and we initialize it with: fibon(0,1,n,[]). In each iteration, it will calculate the next Fibonacci number c = a+b and append it to the result. In case that number is still smaller than c < n then we need to calculate the next number and thus perform the recursive call.
def fibonacci(n):
n = int(n)
def fibon(a,b,n,result):
c = a+b
result.append(c)
if c < n:
fibon(b,c,n,result)
return result
return fibon(0,1,n,[])
print(fibonacci(input("Input a number to print sequence up to: ")))
This uses recursion but much faster than naive recursive implementations
def fib(n):
if n == 1:
return [1]
elif n == 2:
return [1, 1]
else:
sub = fib(n - 1)
return sub + [sub[-1] + sub[-2]]
Here are some examples of how you can improve the speed:
"""
Performance calculation for recursion, memoization, tabulation and generator
fib took: 27.052446
mem_fib took: 0.000134
tabular_fib took: 0.000175
yield_fib took: 0.000033
"""
from timeit import timeit
LOOKUP_SIZE = 100
number = 30
lookup = [None] * LOOKUP_SIZE
def fib(n):
return 1 if n <= 2 else fib(n - 1) + fib(n - 2)
def mem_fib(n):
"""Using memoization."""
if n <= 2:
return 1
if lookup[n] is None:
lookup[n] = mem_fib(n - 1) + mem_fib(n - 2)
return lookup[n]
def tabular_fib(n):
"""Using Tabulation."""
results = [1, 1]
for i in range(2, n):
results.append(results[i - 1] + results[i - 2])
return results[-1]
def yield_fib(n):
"""Using generator."""
a = b = 1
yield a
yield b
while n > 2:
n -= 1
a, b = b, a + b
yield b
for f in [fib, mem_fib, tabular_fib, yield_fib]:
t = timeit(stmt=f"f({number})", number=10, globals=globals())
print(f"{f.__name__} took: {t:.6f}")
I've a small Python (2.7.10) script, which you can see below.
def numbers_calc(max_num, num_step):
"""Returns every number from 0 to max_num with num_step as step."""
n = 0
l = []
while n < max_num + 1:
l.append(n)
n += n * num_step
return l
n_l = []
n_l.append(numbers_calc(25, 1))
print "Here are the numbers."
print n_l
The function numbers_calc is meant to take all the given args, form a list, and populate it with numbers (with num_step as the step when calculating) before it reaches max_num + 1. The script then does return it's local list named l.
However, every time I run the script, I encounter MemoryError. Here's what Python returned when I ran the script:
Traceback (most recent call last):
File "num.py", line 13, in <module>
n_l.append(numbers_calc(25, 1))
File "ex33.py", line 7, in numbers_calc
l.extend(i)
MemoryError
I tried looking it up, saw nothing helpful. I hope you can help me!
n starts at 0. n += n * num_step adds 0 to n. n never changes, and your loop keeps adding items to the list forever.
Cause n to change somehow.
The issue is in the line -
n += n * num_step
Here, you initialized n as 0 , and then you are multiplying n and num_step , whose result would always be 0 , and then adding it to n . So n always stays at 0 . If you are Try to loop from 0 to max_num+1 for every num_step, you should use range() function, Example -
def numbers_calc(max_num, num_step):
"""Returns every number from 0 to max_num with num_step as step."""
l = []
for i in range(0,max_num + 1,num_step):
l.append(i)
return l
anything times 0 is always going to be 0 so you have an infinite loop settingn = 0 set n to 1 initially:
def numbers_calc(max_num, num_step):
"""Returns every number from 0 to max_num with num_step as step."""
n = 1
l = []
while n < max_num + 1:
l.append(n)
n += n * num_step
print(n)
return l
n_l = []
n_l.append(numbers_calc(25, 1))
Output:
[[1, 2, 4, 8, 16]]
If you want a list of number just use the return value:
nl = numbers_calc(25, 1)
Which will give you [1, 2, 4, 8, 16]
If you actually want every number from 0 to max_num with num_step use += not *= and leave n at 0:
def numbers_calc(max_num, num_step):
"""Returns every number from 0 to max_num with num_step as step."""
n = 0
l = []
while n < max_num + 1:
l.append(n)
n += num_step
print(n)
return l
Or simply return range with a step:
def numbers_calc(max_num, num_step):
"""Returns every number from 0 to max_num with num_step as step."""
return list(range(max_num + 1,num_step))
You should be aware that if the step is not a multiple of max_num then you are not going to get max_num i.e numbers_calc(25, 2) will go to 24 .
Thanks everybody for helping! Didn't even realise I had math problems there. Thank you all! By the way, here's the final version of my script.
def numbers_calc(max_num, num_step):
"""Returns every number from 0 to max_num with num_step as step."""
i = 0
l = []
while i < max_num + 1:
l.append(i)
i += num_step
return l
n_l = numbers_calc(25, 5)
print "Here are the numbers."
print n_l
fib = [0,1]
a = 1
b = 0
i = 0
while i < n:
i = a+b
a,b = i, a
fib.append(i)
This works in cases where 'n' (which is a given variable) is a number in an actual Fibonacci sequence, like 21 or 13. However, if the number is something like six, it adds one more number than it should. The list should not contain a number that is greater than n.
You could always add a to the list first, then do your incrementing.
fib = [0]
a, b = 1, 0
while a <= n:
fib.append(a)
a,b = a+b, a
Using the classic shnazzy recursive Fibonacci function (which took me a few tries to remember and get right):
def fib(num):
if ((num == 0) or (num == 1)): return 1
fib_num = fib(num - 1) + fib(num - 2)
return fib_num
x, n, i = 2, 15, []
while (fib(x) < n):
i.append(fib(x))
x += 1