Hello I am trying to generate Fibonacci series by using a recursive function in python.
Here is my code
def fibolist(n):
list1 = [1, 1]
if n in (1,2) :
return list1
else:
fibolist(n-1).append(sum(fibolist(n-1)[n-3:]))
return list1
but when I enter any number as an argument, the result is [1, 1]
Could you please help me?!
You start with
list1 = [1, 1]
You never change that value, and then you return it to the calling routine.
Each invocation of fibolist has a local variable named list1; appending to one does not change the list1 value in the calling program. You need to explicitly do that. Try
else:
return fibolist(n-1) + [sum(fibolist(n-1)[n-3:])]
Just to fix your code:
def fibolist(n):
if n in (0,1) :
return [1,1]
else:
return fibolist(n-1)+[sum(fibolist(n-1)[n-2:])]
Few notes:
lists in python have starting index=0, so it's better start with it (unless you want to put start return to [0,1,1] for n in (1,2)).
Also - as already mentioned you shouldn't return local variable, which you preassign in each go.
Your code is not updating the list1 variable that it returns upon coming back from the recursion. Doing fibolist(n-1).append(...) updates the list returned by the next level but that is a separate list so list1 is not affected.
You could also make your function much simpler by making it pass the last two values to itself:
def fibo(n,a=1,b=1): return [a] if n==1 else [a] + fibo(n-1,b,a+b)
BTW, the modern interpretation of the fibonacci sequence starts at 0,1 not 1,1 so the above signature should be def fibo(n,a=0,b=1).
Output:
print(fibo(5))
#[1, 1, 2, 3, 5]
Related
I am currently trying to code a function recursively but I am stuck on the base case. Basically, my problem is that I don't know how to create the base case since I don't know how to check every element of the list recursively. If I was to use a for loop, it would go something like
for i in range(len(A)):
where A is a list. How would I changed that into recursion?
Edit: I am now aware that I gave too little details. Lets say I have a list of numbers [5,6,-1,7,-3] I want my output to be just the positive numbers, so by the code it would be [5,6,3]. Now my problem is that I can easily do this using a for loop to check every element of the list, but I want to do it recursively and I don't know how to do that for lists. I hope It is clearer now/makes sense.
The base case is when then list element is not a nested list, like follows:
def visit_list_rec(x):
# base case, we found a non-list element
if type(x) != list:
print(x)
return
# recursive step, visit each child
for element in x:
visit_list_rec(element)
if __name__ == "__main__":
visit_list_rec(["this", "is", ["a", ["nested", "list"]]])
This seems to work. The base case is when there are no more numbers left to check.
def positive_vals(nums, result=None):
if result is None:
result = []
if not nums:
return result
else:
if nums[0] > 0:
result.append(nums[0])
return positive_vals(nums[1:], result)
numbers = [5, 6, -1, 7, -3]
print(positive_vals(numbers)) # -> [5, 6, 7]
I am trying to write a small function (as an exercise). This function takes a list of values and returns the values that are odd numbers. I have gotten the function to give me the right answer with the print() function, but I am not able to do the same with a return statement.
def odd_nr(list1):
i = 0
for list1[i] in list1:
if list1[i] % 2 != 0:
print(list1[i])
i += 1
return list1
odd_nr([1,2,3,4,5,6])
The output is:
1
3
5
[1, 3, 5, 6, 5, 6]
I am not able to figure out why the return statement gives this output. I tried different indentations, I tried different variants of the return statement, but I just can't seem to get it to work.
What am I doing wrong?
try:
def odd_nr(list1):
results = []
for number in list1:
if number % 2 != 0:
print(number)
results.append(number)
return results
odd_nr([1,2,3,4,5,6])
Further Explanation:
Any function can take something and return something. This something can also be nothing, None.
Your function takes a list, and returns a list, but it is returning the same list that it is taking in.
The print statement is not a return value. Which means a print is not something that the function returns, it is a side-effect, a side door, for us humans to see, mostly.
To return a list of only odd numbers, you need to collect them in another list as you iterate through your original input list.
Then once you are done, return the list that has collected all the odd numbers. Hope this helps.
I also updated your code a bit, for list1[i] in list1, even though it works, it is hard to understand and it does so for the wrong reasons, see below. You can simply do for number in list1 and also not worry about incrementing any counters(i in your case).
Explanation on why for list1[i] in list works:
This is interesting. By choosing list1[i] as the current iteratee, we will be mutating our list while iterating; it is lucky that each iteratee is equal, in value to the list element it is mutating. Here is an example to illustrate what is happening. It is easy to see when we do not update i:
list1= [1,2,3,4]
i=0
for list1[i] in list1:
print(list1[i])
print(list1)
Output:
1
2
3
4
[4, 2, 3, 4]
You just need to return list1[:i] instead of returning the whole list1. Demo with that:
>>> odd_nr([1,2,3,4,5,6])
1
3
5
[1, 3, 5]
With your unusual but correct for list1[i] in list1 and the according update of i, you're moving all the odd numbers to the front of the list and counting them with i. All that's left to do is to only return that front portion.
Alternatively, delete the unwanted back portion with del list1[i:] before you do return list1.
I'm having trouble with understanding when to use the return function. In the below function my intuition is that the return statement should be there to return the modified list, but my TA said is was redundant which I didn't quite understand why. Any clarification on when to correctly use return statement and on common practise would be highly appreciated.
p = [2,0,1]
q = [-2,1,0,0,1,0,0,0]
p1 = [0,0,0,0]
#Without return statement
def drop_zeros1(p_list):
"""drops zeros at end of list"""
i = 0
while i < len(p_list):
if p_list[-1]==0:
p_list.pop(-1)
else:
break
#With return statement
def drop_zeros(p_list):
"""drops zeros at end of list"""
i = 0
while i < len(p_list):
if p_list[-1]==0:
p_list.pop(-1)
else:
return p_list
break
Also why the output is inconsistent when used on the list p1, it only removes the last 0 when it should remove all zeroes?
Many Thanks,
The convention is that functions either mutate the argument(s) given to it, or return the result, but then leave the arguments untouched.
This is to prevent that a user of your function would do this:
template = [1, 2, 0, 0]
shorter = drop_zeros(template)
print ("input was ", template, " and output was ", shorter)
They would expect this output:
input was [1, 2, 0, 0] and output was [1, 2]
... but be surprised to see:
input was [1, 2] and output was [1, 2]
So to avoid this, you would either:
not return the modified argument, but None. That way the above code would output ...and output was None, and the user would understand that the function is not designed to return the result.
return the result, but ensure that the argument retains its original content
So in your case you could do:
def drop_zeros(p_list):
"""drops zeroes at end of list, in-place"""
while p_list and p_list[-1] == 0:
p_list.pop()
Note that the else can be better integrated into the while condition. No more need to do an explicit break. Also .pop() does not need -1 as argument: it is the default.
If you prefer a function that returns the result, then the logic should be somewhat different:
def drop_zeros(p_list):
"""returns a copy of the list without the ending zeroes"""
for i in range(len(p_list)-1, -1, -1):
if p_list[i] != 0:
return p_list[0:i+1]
return []
Now the code is designed to do:
template = [1, 2, 0, 0]
shorter = drop_zeros(template)
print ("input was ", template, " and output was ", shorter)
# input was [1, 2, 0, 0] and output was [1, 2]
Your TA is right, the return is redundant because of what in python is called aliasing.
Basically, in your function, p_list is a reference (NOT a copy) to whatever list you pass in when you call the function. Since you use pop, which mutates the list in-place when extracting an element, p_list will be modified and this modification will be visible outside the function:
drop_zeros(q) # from here, in the function, p_list is q (as in, exactly the same object)
print(q)
prints
[-2,1,0,0,1]
I have a permutations code and I have to return the output list that contains the list of all permutations. For example if I have [0,1] as the input I need to return [[0,1],[1,0]] as the output. To accomplish that I pass output array as a parameter in the recursive call. Is this a good idea or is it better to create a nested function permute_list inside permute that has access to output list always ? Just wanted to know what a good python user should do.
import copy
def permute(l):
"""
Return a list of permutations
Examples:
permute([0, 1]) returns [ [0, 1], [1, 0] ]
Args:
l(list): list of items to be permuted
Returns:
list of permutation with each permuted item being represented by a list
"""
output = []
if len(l) == 0:
return [[]]
else:
permute_list(l,0,output)
return output
def permute_list(l,ind,output):
if ind == len(l) - 1:
a = l.copy()
output.append(a)
print(f"{output}")
for i in range(ind,len(l)):
l[ind],l[i] = l[i],l[ind]
permute_list(l,ind + 1,output)
l[i],l[ind] = l[ind],l[i]
I have not checked your code for accuracy but to answer your question, there does not seem to be an issue with how output is being handled. output is a list and given that in python variable names serve as references to the object, passing it as a parameter should have no impact on your stack length.
I have a function that modifies a list, however it doesn't return anything. It is a long function but to give an example, the following has the same problem. Why is it not returning anything?
def inventedfunction(list1):
list2=list1[:-1]
if len(list2)!=1:
inventedfunction(list2)
else:
return list2
Replace inventedfunction(list2) with return inventedfunction(list2). If you just call it without the return statement, the result is thrown out.
Working code:
def inventedfunction(list1):
list2=list1[:-1]
if len(list2)!=1:
return inventedfunction(list2)
else:
return list2
You didn't say what the function is supposed to do, so I am assuming that "inventedfunction" means "inverted function". Even if this is not correct, the idea is the same. If this is not the case or you don't understand then post back with more info.
You don't catch any of the returns, and don't return anything (None) if len(list2) != 1. You also would have to create a 2nd list to hold the numbers removed from the list sent to the function, and return the updated list as well according to way your code is structured.
def inventedfunction(list1, new_list=[]):
## at the least add print statements so you know what is happening
print new_list, "----->", list1
list2=list1[:-1]
new_list.append(list1[-1]) ## append item removed from list1 --> list2
if len(list2):
new_list, list2=inventedfunction(list2)
return new_list, list2 ## both updated lists returned
print inventedfunction([1, 2, 3, 4, 5])