Flow of a factorial function using recursion - python-3.x

I'm learning the fundamentals of Python right now by reading Thinking Python.
As I was reading a chapter about "fruitful" function, that is, a function that "returns" a value, I came across this problem. I can more or less figure out how the code of the factorial function works, but not exactly. I have trouble in understanding precisely the flow of a function involving self-calling or recursion. Btw, the printer statments in the code shown as below are scaffolding, a device used to track the flow of the function.
Without further ado, here is the code.
def factorial(n):
space=' '*(2*n)
print(space, 'factorial', n)
if n==0:
print(space, 'returning 1')
return 1
else:
recurse = factorial(n-1)
result=n*recurse
print(space, 'Returning', result)
return result
factorial(3)
The result or the output of this code is shockingly a v-shape. I, for the life of me, cannot figure out why the computer (or the compiler?) runs the program the way it does here. It seems like it firstly prints the first line and the last line, and then goes on to print the second line and the second to the last line...This is strange. You would expect that it always goes top down.
To illustrate the oddity of this issue, I hereby attach another piece of code that prints numbers as you count down. The code is similar and simpler, and you would expect it to behave similarly to the factorial function before. But it doesn't. There is no oddity in the order in which the lines of outcome are displayed or printed off.
def f(n):
print(n)
if n==0:
return 0
else:
print(3*n)
f(n-1)
return
I would really appreciate it if you could help me with this!

What might confuse you is that the recursive call does not happen at the end of the function as it is the case with your example f(). Which means, you have code that is executed before stepping into the recursion and code that is executed after stepping out of the recursion. Let's have a look at what happens in factorial:
The recursive step
Pick any recursion step i you like, which is not a base case. And then look at what the function does, without following through with the recursion.
For your factorial function, let's take the call factorial(i), where iis different from 0. That call does three things:
print 2*i spaces and "factorial i"
call factorial(i-1)
print 2*i spaces and "returning i"
So, the output is going to be:
(2*i spaces) factorial i
# everything factorial(i-1) outputs
(2*i spaces) returning i
You'll see that the output of factorial(i-1) gets sandwiched between the outputs of factorial(i). To perform the recursion, all you need to do is blow the pattern up. Let's take another step i-1 into account:
(2*i spaces) factorial i
(2*(i-1) spaces) factorial i-1
# everything factorial(i-1) outputs
(2*(i-1) spaces) returning i-1
(2*i spaces) returning i
So, you see that the indentation decreases with the calls since i decreases, which accounts for the v-shape.
The base case
It just prints
factorial 0
returning 1
Putting it all together
Now, you can find a verbal expression for what factorial(i) does:
factorial(i) produces the v-shape output
factorial i
factorial i-1
...
factorial 0
returning 1
...
returning i-1
returning i
With it being true for the case i == 0, conclude from there that is is true for i+1 if you assume that is is correct for i using the list in the section recursive step. Done that, you can be sure that is how factorial(n) works for any n >= 0.

Here's your code a bit restructured to make it easier to see:
def factorial(n):
space = ' '*(2*n)
print(space, 'factorial', n)
result = 1 if n == 0 else n*factorial(n-1)
print(space, 'Returning', result)
return result
And that's the output for factorial(3) with the "V shape" you mentioned:
factorial 3
factorial 2
factorial 1
factorial 0
Returning 1
Returning 1
Returning 2
Returning 6
It looks correct and does the job of calculating the factorial. To understand the order of prints seen here, think of the following:
The prints start with the call for 3, since that's your entry point
The indentation is then 3x2 = 6 spaces
Since for the calculation of factorial(3) the reuslt of factioral(2) is needed, this call comes next, with an indentation of 2x2 = 4 spaces. And so on for all further factorials. That's where the V shape of the first half of prints comes from.
All of these function calls are now "waiting" for a result to return, at the position of the recursive call in the code. Since only factorial(0) can deliver that return value without another recursion, it will print the first return value. With an indentation of 0.
With the above return value, the function call to factorial(1) can now calculate its result by multiplying the returned 1 with its own n, which gives 1. That's the next print, with an indentation of 2.
And so on for all the higher recursion steps, from the inside to the outside. And that's how the second half of the V shape is formed.
The vital thing to understand is that the result values of the functions (and thereby the print) can only occur at the END of the complete recursion tree that comes below it. That's why the call print factorial 3 is in the first line, while its corresponding Returning 6 print is at the last line - after the whole inner tree is finished.
Hard to say if I picked up the crunchpoint you had trouble understanding with, but I hope this somehow helps.
EDIT: infinite recursion
As an answer to your question, here's an example that shows how each recursive function call will have its own variable scope and therefore not know about the variables set in an another instance of the same function, ending up in a RecursionError when the maxiumum recursion depth of the call stack is reached.
def foo():
try:
print("a = ", a)
return # break out of loop
except UnboundLocalError:
print("no variable a. defining one now.")
a = 3
foo() # try again
foo()

Related

Is the 'for loop' for x used in this code a valid substitute for while x<=num?

I am trying to solve this problem of displaying prime numbers upto a specified number.
While I have the standard solution for it. I first tried to solve it myself and ended up writing this code. But I'm not getting the desired output. The standard solution uses the while loop as the main loop. And if that's the ideal loop for this example, why would that be so ?
def count_primes(num):
my_primes=[2]
if num<2:
return 0
for x in range(3,num+1,2):
for y in range(3,x+1):
if x%y==0:
break
else:
my_primes.append(x)
return my_primes
count_primes(100)
I expected a list of all prime numbers up to 100. Instead the output displayed only [2]. My guess is that the 'break' keyword broke out of the entire loop instead of only the if loop.
In your second for loop change range(3,x+1) to range(3,x), since your loop goes until y=x and x%x is always 0.

Sequence of legal pairs of parentheses using recursion - Python

I have some problem to solve using recursion in Python.
I'm simply bad in recursion and don't know how to start so please guide me.
We will say that a string contains 'n' legal pairs of parentheses if the string contains only the chars '(',')' and if this sequence of parentheses can be written so in a manner of mathematical formula (That is, every opening of parentheses is closed and parentheses are not closed before they are opened). More precise way to describe it is at the beginning of the string the number of '(' is greater or equal to ')' - and the number of any kind of char in the whole string is equal. Implement a function that recieves a positive integer n and returns a list which contains every legal string of n-combination of the parentheses.
I have tried to start at least, think of a base case, but what's my base case at all?
I tried to think of a base case when I am given the minimal n which is 1 and then I think I have to return a list ['(', ')']. But to do that I have also a difficulty...
def parentheses(n):
if n == 1:
return combine_parent(n)
def combine_parent(n):
parenth_lst = []
for i in range(n):
parenth_lst +=
Please explain me the way to solve problems recursively.
Thank you!
Maybe it's helpful to look in a simple case of the problem:
n = 2
(())
()()
So we start by n=2 and we produce a sequence of ( n times followed by a sequence of ) n times and we return a list of that. Then we recursively do that with n-1. When we reach n=1 it looks like we reached the base case which is that we need to return a string with () n times (not n=1 but n=2).
n = 3
((()))
(())()
()()()
Same pattern for n=3.
The above examples are helpful to understand how the problem can be solved recursively.
def legal_parentheses(n, nn=None):
if nn == 1:
return ["()" * n]
else:
if not nn:
nn = n
# This will produce n ( followed by n ) ( i.e n=2 -> (()) )
string = "".join(["(" * nn, ")" * nn])
if nn < n:
# Then here we want to produce () n-nn times.
string += "()" * (n-nn)
return [string] + legal_parentheses(n, nn-1)
print(legal_parentheses(3))
print(legal_parentheses(4))
print(legal_parentheses(5))
For n = 3:
['((()))', '(())()', '()()()']
For n = 4:
['(((())))', '((()))()', '(())()()', '()()()()']
For n = 5:
['((((()))))', '(((())))()', '((()))()()', '(())()()()', '()()()()()']
This is one way of solving the problem.
The way to think about solving a problem recursively, in my opinion, is to first pick the simplest example of your problem in your case, n=2 and then write down what do you expect as a result. In this case, you are expecting the following output:
"(())", "()()"
Now, you are trying to find a strategy to break down the problem such that you can produce each of the strings. I start by thinking of the base case. I say the trivial case is when the result is ()(), I know that an element of that result is just () n times. If n=2, I should expect ()() and when n=3 I should expect ()()() and there should be only one such element in the sequence (so it should be done only once) hence it becomes the base case. The question is how do we calculate the (()) part of the result. The patterns shows that we just have to put n ( followed by n ) -> (()) for n=2. This looks like a good strategy. Now you need to start thinking for a slightly harder problem and see if our strategy still holds.
So let's think of n=3. What do we expect as a result?
'((()))', '(())()', '()()()'
Ok, we see that the base case should still produce the ()()() part, all good, and should also produce the ((())) part. What about the (())() part? It looks like we need a slightly different approach. In this case, we need to somehow generate n ( followed by n ) and then produce n-1 ( followed by n-1 ) and then n-2 ( followed by n-2 ) and so on, until we reach the base case n=1 where we just going to produce () part n times. But, if we were to call the function each time with n-1 then when we reach the base case we have no clue what the original n value was and hence we cannot produce the () part as we don't know how many we want (if original n was 3 then we need ()()() but if we change n by calling the function with n-1 then by the time we reach the base case, we won't know the original n value). Hence, because of that, in my solution, I introduce a second variable called nn that is the one that is reduced each time, but still, we leave the n unmodified so we know what the original value was.

Receiving function as another function´s parameter

Let´s say I have 2 functions like these ones:
def list(n):
l=[x for x in range(n)]
return l
def square(l):
l=list(map(lambda x:x**2,l))
print(l)
The first one makes a list from all numbers in a given range which is "n" and the second one receives a list as a parameter and returns the squared values of this list.
However when I write:
square(list(20))
it raises the error "map object cannot be interpreted as an integer" and whenever I erase one of the functions above and run the other one it runs perfectly and I have no idea what mistake I made.
You redefined the standard function list()! Rename it to my_list() and clean the code accordingly.
As a side note, your function list() is doing exactly what list(range(n)) would do. Why do you need it at all? In fact, for most purposes (including your example), range(n) alone is sufficient.
Finally, you do not pass a function as a parameter. You pass the value generated by another function. It is not the same.

A Function That Counts The Number of Loops

Write a function multisplit that consumes two positive integers total and split and produces the number of times total is repeatedly divided into split even pieces before each piece is of size at most 1. For example, the value returned by multisplit(8, 2) will be 3, since 8 can be split into 2 pieces of size 4, which are then each split into 2 pieces of size 2, which are then each split into 2 pieces of size 1 (at which point no further splitting takes place since the pieces are of size at most 1).
total= int(input("Total:"))
split= int(input("Split:"))
def multisplit(total,split):
x=o
while value>=1:
value= total//split
x= x+1
return x
print(x)
It's telling me that the name 'x' is not defined
There are several issues with the code you posted:
In python, the contents of a function must be indented.
def myfunction():
# code inside the function goes here
# code after you've unindented is not in the function
You didn't define your value variable before using it.
Assuming that your final line gets appropriately unindented, so that it won't be completely ignored because of being inside the function, but after the return statement:
You're trying to print the value of a variable that was defined in a different scope. Specifically, you defined x inside the function, and now you're trying to look at it outside the function.
You never called your function...
If I understand what you're trying to do, you want to call the function inside print. i.e.: print(multisplit(total, split))

Funny Haskell Behaviour: min function on three numbers, including a negative

I've been playing around with some Haskell functions in GHCi.
I'm getting some really funny behaviour and I'm wondering why it's happening.
I realized that the function min is only supposed to be used with two values. However, when I use three values, in my case
min 1 2 -5
I'm getting
-4
as my result.
Why is that?
You are getting that result because this expression:
min 1 2 -5
parses as if it were parenthesized like this:
(min 1 2) -5
which is the same as this:
1 -5
which is the same as this:
1 - 5
which is of course -4.
In Haskell, function application is the most tightly-binding operation, but it is not greedy. In fact, even a seemingly simple expression like min 1 2 actually results in two separate function calls: the function min is first called with a single value, 1; the return value of that function is a new, anonymous function, which will return the smaller value between 1 and its single argument. That anonymous function is then called with an argument of 2, and of course returns 1. So a more accurate fully-parenthesized version of your code is this:
((min 1) 2) - 5
But I'm not going to break everything down that far; for most purposes, the fact that what looks like a function call with multiple arguments actually turns into a series of multiple single-argument function calls is a hand-wavable implementation detail. It's important to know that if you pass too few arguments to a function, you get back a function that you can call with the rest of the arguments, but most of the time you can ignore the fact that such calls are what's happening under the covers even when you pass the right number of arguments to start with.
So to find the minimum of three values, you need to chain together two calls to min (really four calls per the logic above, but again, hand-waving that):
min (min 1 2) (-5)
The parentheses around -5 are required to ensure that the - is interpreted as prefix negation instead of infix subtraction; without them, you have the same problem as your original code, only this time you would be asking Haskell to subtract a number from a function and would get a type error.
More generally, you could let Haskell do the chaining for you by applying a fold to a list, which can then contain as many numbers as you like:
foldl1 min [1, 2, -5]
(Note that in the literal list syntax, the comma and square bracket delimit the -5, making it clearly not a subtraction operation, so you don't need the parentheses here.)
The call foldl1 fun list means "take the first two items of list and call fun on them. Then take the result of that call and the next item of list, and call fun on those two values. Then take the result of that call and the next item of the list..." And so on, continuing until there's no more list, at which point the value of the last call to fun is returned to the original caller.
For the specific case of min, there is a folded version already defined for you: minimum. So you could also write the above this way:
minimum [1, 2, -5]
That behaves exactly like my foldl1 solution; in particular, both will throw an error if handed an empty list, while if handed a single-element list, they will return that element unchanged without ever calling min.
Thanks to JohnL for reminding me of the existence of minimum.
When you type min 1 2 -5, Haskell doesn't group it as min 1 2 (-5), as you seem to think. It instead interprets it as (min 1 2) - 5, that is, it does subtraction rather than negation. The minimum of 1 and 2 is 1, obviously, and subtracting 5 from that will (perfectly correctly) give you -4.
Generally, in Haskell, you should surround negative numbers with parentheses so that this kind of stuff doesn't happen unexpectedly.
Nothing to add to the previous answers. But you are probably looking for this function.
import Data.List
minimum [1, 2, -4]

Resources