Reputation: 857
def codes(r):
'''(int) -> list of str
Return all binary codes of length r.
>>> binary_codes(2)
['00', '01', '10', '11']
'''
if r == 0:
return ['']
small = codes(r-1)
lst = []
for item in small:
lst.append(item + '0')
lst.append(item + '1')
return lst
Currently learning recursion and confused as to how this function exactly works. It's supposed to return a list of strings of binary code of length r (as per the docstring) using the knowledge that you can add 0 and 1 to each 'binary code' to obtain the amount of strings in the next one.
Now where I'm confused is the small = codes(r-1) part
If I trace this through, it seems to just continually call the function until 'r == 0' is true where in that case, it ends off returning empty? Appending 0 and 1 to an empty list would seemingly only give you ['0', '1']. How does this function manage to return all binary codes of length r using that base case.
Upvotes: 2
Views: 127
Reputation: 15310
The key to a recursive function is to know when to quit! Each recursive function, or at least one member of a group of mutually-recursive functions, will have a test that simply says, "This is the end, or start, or bottom, or top of whatever, and so the result is a constant, or an empty string, or a null list, or whatever."
Terminating
Your termination condition is r == 0
. And when asked for all binary strings of length zero, you are returning ['']
- a list containing the empty string. Why? Because there are no such strings, but in order to make a longer string (see below) we need a string to append to.
Iterating
When not in a "this is the end" case, the recursive function needs to compute "one more step" in the process. Since the terminating condition for your function is based on the length of the string, your iterating condition will probably also be based on string length. In this case, you recurse by making the string shorter. So you iterate by making the (shortened) string longer.
If you have a binary string like '0', what are all the possible binary strings that are one character longer than that? Well, they are either ['01', '00'] or ['10', '00'] depending on whether you want to make strings longer at the end or at the beginning.
So how do you make a list of binary strings of length N? Well, first you get every possible binary string of length N-1 and then you make two strings for each one of those, with a zero or a one attached.
How can you get every possible binary string of length N-1? You can call this function, codes(N-1)
and it will return them. Don't worry about how!
So small = codes(r-1)
is your function getting a list of strings that are one character shorter -- the r-1
part. Then you iterate over each one, and make two! One will be the string plus '0', the second will be the string plus '1'. Once you have iterated over all the small
-er strings, you have a list of longer strings. You can pass this result out to whoever asked for it (which might be yourself, trying to make even longer strings).
Upvotes: 1
Reputation: 27323
Let's look at this for r=2:
codes(2)
r is not 0, so we don't return anything. small
get's assigned the return value of codes(1)
. So to continue, we have to look at what codes(1)
returns first.
codes(1)
Again, r is not 0. So the small
inside this call is set to codes(0)
. We have to look at what codes(0)
returns.
codes(0)
This is hardcoded to return ['']
. Let's go back to the execution of codes(1)
codes(1)
(cont.)small
was set to ['']
, now we iterate over every element of that list, but first, we define an empty list lst
. small
has only one element, ''
. So we append two elements to lst
: '' + '0'
(which is just '0'
), and likewise '1'
.
Then we return the list. So now we know that codes(1)
returns ['0', '1']
. Let's go back to the execution of codes(2)
codes(2)
(cont.)small
gets assigned the result of codes(1)
, which we now know to be ['0', '1']
. Now we initialize an empty list lst
again, and iterate over small
. For every element in small
(we have two), we append two elements to lst
: That means to 0
we append both 0
and 1
to obtain 00
and 01
, and the same for 1
, to obtain 10
and 11
.
codes(2)
returns ['00', '01', '10', '11']
.In general you will see that for each element in the result of codes(n)
, codes(n+1)
will return two elements: That element with 0
and 1
appended, respectively. So the length of the returns list always doubles, as it should.
It is important to understand that although the names small
and lst
are fixed, they refer to different objects in each call of codes
, I think that might be the cause of your confusion.
Upvotes: 3