Count elements in list via a recursive method - python

I'm trying to get a grasp on recursion. In general I understand what it does, but I'm having some trouble understanding how the following method works.
def count_numbers_in_list(list):
if list == []:
return 0
return 1 + count_numbers_in_list(list[1:])
Now I get that list[1:] returns everything from the given list except the first.
But what I can't get my head around is that we are never calling something like - 1 on the list itself. So this function works perfectly, but it would also make sense to me that this function returns a infinite loop.
I'm hoping that somebody could explain precisely to me what's happening here.
Thanks!

Now I get that list[1:] returns everything from the given list except the first.
Actually you've already found out the answer explaining why that function works perfectly.
return 1 + count_numbers_in_list(list[1:])
Every time recursion is performed, count_numbers_in_list is given a shorter list until there is no element left in it:
Let's break this down. Consider you have the below list:
lst = [1, 2, 3, 4]
count_numbers_in_list is given [1, 2, 3, 4] at first:
0 + count_numbers_in_list([1, 2, 3, 4])
(0 + (1 + count_numbers_in_list([2, 3, 4]))
(1 + (1 + count_numbers_in_list([3, 4]))
(2 + (1 + count_numbers_in_list([4]))
(3 + (1 + count_numbers_in_list([])))
(4 + (count_numbers_in_list([])))
(4 + 0)
Result is 4.

This recursive counting method is basically saying "if my list is empty, that's my base case. There are 0 elements here. Otherwise, I can count just one of the elements, and then I can count the rest of the list."
So "1+" is saying "count one of the elements". "count_numbers_in_list(list[1:])" is saying "count everything except the first element in the list."
Then you just think of it as deferred execution of some sort, or a stack if you're familiar with that. Say I have the list [1, 2, 3]. The recursive statement says "return 1 plus whatever you calculate as the result of count([2, 3])". Similarly, the answer to [2,3] is 1 plus whatever the answer to [3] is. 3 is 1 + the answer to [], and our base case says the answer to [] is 0. So [3] resolves as 1 + 0 = 1, and passes it back up to [2, 3]. That resolves as 1 + 1 = 2, and 2 gets passed back up to the result for [1, 2, 3]. That resolves as 1 + 2 = 3, and that's your final answer.

Related

Trying to make a "folded list" in python?

I need to make a "folded in half list" where I multiply the first and last term, second and second to last term, third and third to last term, etc.
I know how to make a list and how to print specific values from the list, but don't understand how to do math like this within the list, without simply typing each number and multiplying them.
So far all I have is a list (called a) with six terms, and though I know how to multiply the whole times an integer, I don't know how to make this "folded" thing. Will I need to end up making a loop of some sort? If so, how?
Edit: I should have specified that I need to make it via a function. Someone helped me make one via a method that worked great, but when I realized it needed to be a function I tried it again and it won't work. See the code below.
a = [10, 14, 21, 25 ,52, 55]
print('starting list:', a)
Finding the middle of the list
len(a)//2
Using (what I think is) a function to make a new list of first + last term, etc.
Term i is the term counted from the start of the list, term -(i+1) is the term counted from the bottom of the list
print(sum((a[i]) + (a[-(i + 1) ])) for i in range( len(a) // 2)
A code that works but isn't a function since it has brackets
foldedlist=[ a[i] + a[-(i + 1) ] for i in range( len(a) // 2)]
print('folded list:', foldedlist)
Take your list, here:
l = [1, 2, 3, 4, 5, 6]
Find the mid-way point (where the fold happens - you'll need to think about how this works for an odd-numbered length list)
l_mid = len(l) / 2
Make two sublists up to, and then from the mid-point
l1 = l[:l_mid]
l2 = l[l_mid:]
Create a container for the output and then iterate over both lists, with the latter reversed and append the product to the container.
output = []
for v1, v2 in zip(l1, reversed(l2)):
output.append(v1 * v2)
As we know, indexes in list can be positive or negative. Index -1 refers to last item, index -2 refers to second last item, etc. Hence, we must have:
L[0]*L[-1]+
L[1]*L[-2]+
L[2]*L[-3]+
...+
L[mid]*L[-(mid+1)]
The general formula is: L[i]*L[-(i+1)]. So, we can use the following code:
list = [1, 2, 3, 4, 5, 6]
newList=[ list[i] * list[-(i + 1) ] for i in range( len(list) // 2)]
print(newList)
len(list) // 2 is the index of middle of list.
Output: [6, 10, 12]
Try like this:
myList = [Yourlist]
newList = []
a = myList[:len(myList)//2]
b = myList[len(myList)//2:]
b.reverse()
for x,y in zip(a,b):
newList.append(x*y)

Understand where total value is stored in recursive function - Python

I am trying to understand where the total value is stored for example the return of this function is the int 15. Each number from the input list is taken and added one at a time and removed from the list but I cannot see where the temp value is stored I only get the complete total?
Also regarding return L[0] + mysum(L[1:])ifmysum(L[1:]) stores the list how can it be added with L[0] and if mysum(L[1:]) does not store the list where is the list stored is it not lost and then surely the program would not know what numbers to add next?
Code
def mysum(L):
print(L) # Trace recursive levels
if not L: # L shorter at each level
return 0
else:
return L[0] + mysum(L[1:])
total = mysum([1, 2, 3, 4, 5])
print("Total = ", total)
Return
[1, 2, 3, 4, 5]
[2, 3, 4, 5]
[3, 4, 5]
[4, 5]
[5]
[]
Total = 15
The intermediate running totals are never "stored" in a variable - they are passed down the call stack each time one of the recursive calls returns:
The first recursive call to return is mysum([]) which returns the number 0.
After this, the recursive call mysum([5]) returns 5 + 0 = 5.
After this the recursive call mysum([4,5]) returns 4 + 5 = 9.
Then the recursive call mysum([3,4,5]) returns 3 + 9 = 12.
Then mysum([2,3,4,5]) returns 2 + 12 = 14.
Then finally, the original non-recursive call mysum([1,2,3,4,5]) returns 1 + 14 = 15.
I have an interactive demo which shows how some recursive functions are computed step-by-step using a call stack. It may help you to understand how recursive functions are executed.
The value is "stored" using the fact that before returning an expression, you have to calculate both sides.
In your example, on the first call the last "return" will be "return 1 + mysum([2, 3, 4, 5])", then mysum will be evaluated, it will be evaluated to "return 2 + mysum([3, 4, 5])".
Finally, when you've reached the end of the list, mysum return 0, so it will be "return 1 + 2 + 3 + 4 + 5 + 0".

why the swapping does not take place when indices are 0 and 1?

I have an unordered array consisting of consecutive integers [1, 2, 3, ..., n] without any duplicates. It is allowed to swap any two elements. I need to find the minimum number of swaps required to sort the array in ascending order.
Starting from the first element of the list, I try to put them in their right position (for example if the first element is 7 it should be in the 6th position of the list). To go one by one in the list, I make a copy, and do the swapping in the second list.
a = [4,3,1,2]
b = a[:]
swap = 0
for p in a:
if (p!= b[p-1]):
b[p-1], b[b.index(p)] = b[b.index(p)], b[p-1]
swap+=1
print(swap)
this code works, except for the case that I have to swap two elements in the list whose position is either 0 or 1, in this case . which I don't understand why?? since I'm not exceeding the limit.
Can anyone please explain to me why this happens?
For example, if I print p, two indices where swapping happens, updated list of b and updated number of swaps:
p = 4
idx1= 3 idx2= 0
b= [2, 3, 1, 4]
swap = 1
p = 3
idx1= 2 idx2= 1
b= [2, 1, 3, 4]
swap = 2
p = 1
idx1= 0 idx2= 1
b= [2, 1, 3, 4]
swap = 3
p = 2
idx1= 1 idx2= 0
b= [1, 2, 3, 4]
swap = 4
In this case, you can see that for p = 1, when indices are 0 and 1, the swapping is not taking place.
I changed the order of b[p-1], b[b.index(p)] and I don't have the same problem anymore, but I don't understand the reason.
I have encountered the same problem before, and stucked for a while. The reason to cause this is the order of multiple assignment.
b[p-1], b[b.index(p)] = b[b.index(p)], b[p-1]
Actually multiple assignment is not exactly assign at the same time. pack and unpack mechanism behind this. so it will change b[p-1] first, and b.index(p) in b[b.index(p)] will be find a new index which is p-1 when the case p=1 idx1=0 idx2=1
if you change the assignment order, it will work fine.
b[b.index(p)], b[p - 1] = b[p - 1], b[b.index(p)]
or calculate idx first:
idx1, idx2 = p - 1, b.index(p)
b[idx1], b[idx2] = b[idx2], b[idx1]
I recommend the second version, because first version will do index twice. cost twice time than second version.
you can refer to my related question here: The mechanism behind mutiple assignment in Python
by the way, I think your algorithm is inefficient here, to decrease swap time, but use O(n) index operation, and also copy a array here. I think you can use the same idea, just swap in orignal array.

Python -While loop to recursive [closed]

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 4 years ago.
Improve this question
How do you convert the code below to recursive ?
def fibonacci(n):
a, b = 0, 1
fibonacci = [0]
while a < n:
fibonacci.append(b)
a, b = b, a+b
print ('The fibonacci sequence is : '+" ".join(map(str,fibonacci)))
so basically I'm trying write a function fibonacci that receives a
number as parameter and computes the fibonacci series up to that number.
I was able to come up with the above iteration method but it has to be recursive.
This is what I have done so far in terms of converting to recursive but it's not giving me the output I need
def fibo(n, a = 0, b = 1, fib = [0]):
if a < n:
fib.append(b)
a, b = b, a + b
return fib
return fibo(n, a, b, fib)
how about this ?:
def fibonacci(n, a=0, b=1):
if a >= n : return [a]
return [a] + fibonacci(n,b,a+b)
[EDIT] Here's how it works:
The function progressively builds an array by adding one element [a] to the result of the next call to itself.
The first line allows it to stop when the target is reached. Without it, the second line of the function would keep calling itself and there would never be a result coming back from the recursion.
Because the parameters of a function are local to each call, the value of a and b in the second call are different from the previous ones.
If we follow the logic for fibonacci(7), we get:
1) fibonacci(n=7, a=0, b=1) ==> will return [0] + fibonacci(7,1,1).
2) fibonacci(n=7, a=1, b=1) ==> will return [1] + fibonacci(7,1,2).
3) fibonacci(n=7, a=1, b=2) ==> will return [1] + fibonacci(7,2,3).
4) fibonacci(n=7, a=2, b=3) ==> will return [2] + fibonacci(7,3,5).
5) fibonacci(n=7, a=3, b=5) ==> will return [3] + fibonacci(7,5,8).
6) fibonacci(n=7, a=5, b=8) ==> will return [5] + fibonacci(7,8,13).
7) fibonacci(n=7, a=8, b=13) ==> 8 >= 7 so the first line returns [8]
At that point there are no more recursive calls (the first line returns without calling the function again) and the return values start coming back up.
7) returns [8]
6) returns [5,8]
5) returns [3,5,8]
4) returns [2,3,5,8]
3) returns [1,2,3,5,8]
2) returns [1,1,2,3,5,8]
1) returns [0,1,1,2,3,5,8]
One way to think about recursive functions is to look only at the incremental work to be done on the result that would be produced by a prior parameter value. Most of the time this part of the logic applies backwards (i.e computing the end result based on a previous one). For example, a factorial can be thought of as the multiplication of a number with the factorial of the previous number.
This gives you the equivalent of the second line.
Once you have that down, all you need to decide is the condition that makes the recursion stop. Usually this corresponds to the smallest/simplest use case. For example, a factorial does not need to recurse when the number is less than 2 so the function can return 1 directly.
This gives you the equivalent of the first line.
As you can see in the above tracing, the function will proceed "forward" but actually ends up waiting for a result from itself (with different parameters) before being able to complete the process. This is how recursive functions work. The final result is typically built when the return values come back up from the stack of multiple self-calls.
Your fibonacci function is a bit trickier than a factorial because the series can only be computed from the original (0,1) values. Unlike the factorial, we don't have enough information to figure out the value of a and b based on the supplied parameter (n).
And, if you'd like to sink you teeth in cryptic code, here's a one line version:
def fibo(n,a=0,b=1):return [a]+fibo(n,b,a+b) if a < n else [a]
The point of a recursive implementation is to organize things like this:
if we're at a base case:
return the result for that base case
else:
call ourselves with a reduced case
possibly modify the result
return the result
For the base case, a < n, what you do should be related to what you do after the while loop in the iterative version. Adding the last value to the accumulator list fib and returning it makes sense. It may or may not be right, but it's at least in the right direction.
But in your recursive case, you're not calling yourself with a reduced case, you're just calling yourself with the exact same arguments. That's obviously going to be an infinite loop. (Well, Python doesn't do tail call elimination, so it's going to be a stack overflow, which shows up as a max recursion exception, but that's no better.)
So, what should you be doing? Something related to what happens inside the original non-recursive while loop. What you were doing there is:
fibonacci.append(b)
a, b = b, a+b
So, the equivalent is:
fib.append(b)
return fibo(n, b, a+b, fib)
Again, that may not be right, but it's in the right direction. So, if you get the idea, you should be able to carry on from there to debugging the full function.
I think that Dash's answer is correct, modulo a couple of colons. The original question ask for the computation, not printing.
I've added a dict to store computed values to speed things up a bit, and this code works for me:
fib = {}
fib[0] = 0
fib[1] = 1
def fibonacci(n):
if n not in fib.keys():
fib[n] = fibonacci(n - 1) + fibonacci(n - 2)
return fib[n]
if __name__=="__main__":
for i in range(10):
print i, fibonacci(i)
Output:
0 0
1 1
2 1
3 2
4 3
5 5
6 8
7 13
8 21
9 34
recursion is a functional heritage
Recursion is a concept that comes from functional style. Mixing imperative-style mutations (like append) and reassignments like a, b = b, a + b is a source of much pain and confusion for new programmers
def fibseq (n, a = 0, b = 1, seq = []):
if n == 0:
return seq + [a]
else:
return fibseq (n - 1, b, a + b, seq + [a])
for x in range (10):
print (fibseq (x))
# [0]
# [0, 1]
# [0, 1, 1]
# [0, 1, 1, 2]
# [0, 1, 1, 2, 3]
# [0, 1, 1, 2, 3, 5]
# [0, 1, 1, 2, 3, 5, 8]
# [0, 1, 1, 2, 3, 5, 8, 13]
# [0, 1, 1, 2, 3, 5, 8, 13, 21]
# [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
def fibonacci(n):
if n == 0:
return 0
elif n == 1
return 1
else
return fibonacci(n - 1) + fibonacci(n - 2)

Trying to understand recursion in Python

I've been trying to understand the following code, it's a recursion example from my Python book:
def mysum(L):
if not L:
return 0
else:
return L[0] + mysum(L[1:])
print(mysum([1, 2, 3, 4, 5]))
output: 15
I have a very hard time to understand how this works, and how it is returning 15.
I've tried to rewrite the code as:
def mysum(L):
if not L:
return 0
else:
temp = L[0] + mysum(L[1:])
print(temp)
return temp
mysum([1, 2, 3, 4, 5])
this outputs:
5
9
12
14
15
But i'm still not sure how this works, it's like it starts to sum backwards.
5 + 4 + 3 + 2 + 1
return L[0] + mysum(L[1:])
I know that functions on the right get executed before the function returns anything. In this case it's recursive, it calls itself until L has no elements in it. But if it calls itself again, wouldn't that mean that it again doesn't return anything? This is very confusing to me.
L[0] is the head of the list and L[1:] is the rest. In each call the function adds the first element and the sum of the remaining list.
So what is happening is:
mysum([1, 2, 3, 4, 5]) => 1 + mysum([2, 3, 4, 5])
mysum([1, 2, 3, 4, 5]) => 2 + mysum([3, 4, 5])
mysum([1, 2, 3, 4, 5]) => 3 + mysum([4, 5])
mysum([1, 2, 3, 4, 5]) => 4 + mysum([5])
mysum([1, 2, 3, 4, 5]) => 5 + mysum([])
mysum([]) => 0
After the last call everything everything returns.
Maybe it would be helpful for you to print not only your temp but also L.
it's like it starts to sum backwards.
Well that's because it kind of does, this is an example of tail recursion which is not optimized in python, imagine replacing the mysum(L[1:]) with the result in brackets, you would get something like this:
#L[0] + mysum(L[1:])
mysum([1,2,3,4,5])
1 + mysum([2,3,4,5])
1 + (2 + mysum([3,4,5]))
1 + (2 + (3 + mysum([4,5])))
1 + (2 + (3 + (4 + mysum([5]))))
1 + (2 + (3 + (4 + (5 + mysum([])))))
1 + (2 + (3 + (4 + (5 + 0))))
The inner most level of recursion must finish evaluating before the above levels can, so it only actually starts adding the numbers together once the list has been exhausted and then starts will last recursive call. (the end of the list)
But if it calls itself again, wouldn't that mean that it again doesn't return anything?
Well yes, but only until it can return something without requiring another recursive call, then it can return something, and then the level above can return, then the level above...
Let's follow your first part of code, we call it with the list [1,2,3,4,5]
The first call has L = [1,2,3,4,5] so gets into the second portion and does:
return 1 + mysum([2,3,4,5])
mysum is called again, now with a smaller list, which does:
return 2 + mysum([3,4,5])
Next up:
return 3 + mysum([4,5])
Then:
return 4 + mysum([5])
One more time with the normal flow:
return 5 + mysum([])
This time our passed list is empty and our function returns 0. This cascades back on the stack, which means mysum([5]) now evaluates to 5 (5+0=5), this leads to an evaluation of mysum([4,5]) etcetera all the way up to our first call which returns 15.
Consider this code:
def mysum0(L):
return 0
def mysum1(L):
return L[0] + mysum0(L[1:])
def mysum2(L):
return L[0] + mysum1(L[1:])
def mysum3(L):
return L[0] + mysum2(L[1:])
def mysum4(L):
return L[0] + mysum3(L[1:])
print(mysum4([1, 2, 3, 4]))
Each function mysum[n] sums a list of length n and delegates to mysum[n-1] to help it out. Can you understand how that works? The recursive mysum function is like all the mysum[n] functions combined into one. It only needs to know how to handle a length of list 0 and how to take care of one layer.
You can test the hypothetical question you raised: What happens when the recursion gets to the point that the list has only one element in it?
>>>print(mysum([5]))
returns:
5
Because it executes:
return L[0] + mysum(L[1:])
L[0] returns 5, and mysum(L[1:]) (because L[1:] doesn't exist with a list of length 1) returns 0.
So, now that the function has done that, it can compute the next mysum in the recursion, for L = [4, 5], which turns into:
return L[0] + mysum[L[1:]
which is equivalent to:
return 4 + mysum[5]
which, since we calculated mysum[5] = 5, is equivalent to:
return 4 + 5

Categories

Resources