-1

I'm a beginner to CS, and I've been trying to work through a Python book (Think Python) on my own.

I'm currently on recursion, but I'm a bit stuck.

The exercise asks for me to write a function called do_n that takes a function object and a number, n, as arguments, and that calls the given function n times.

This is my code:

def countdown(n):
    if n<= 0:
        print 'Blastoff'
    return
else:
    print n
    countdown(n-1)

def do_n(f(n), x):
    if x<=0:
        return
    else:
        f(n)
        do_n(f, x-1)
    
do_n(countdown(3), 3)

When I do this, there's an error because of invalid syntax in def do_n(f(n), x). If I change it to:

def do_n(f, x):
    if x<=0:
        return
else:
    f(n)
    do_n(f, x-1)

There is an error because n is not defined in the else statement.

How can I make this work?

ggorlen
  • 44,755
  • 7
  • 76
  • 106
Eric Syu
  • 21
  • 1
  • 3
    Indentation matters. Fix it. – user2864740 Sep 10 '14 at 23:35
  • I think you were using tabs when you posted the code sample. Life gets much easier when you start using 4 space indents with python instead of tabs (see about configuring your editor that way). Its the standard way we deal with python indentation craziness. – tdelaney Sep 11 '14 at 00:41

3 Answers3

0

You are almost there with your second example. It takes a function f and a max count x. n doesn't exist because you haven't written the loop to generate values for n yet. Turns out python has a builtin for that

def do_n(f, x):
    for n in range(x):
        f(n)

Now do_n takes a function object f and a count x, then calls the function count times. Notice the difference between f (the function object) and f(n) (the result of calling f with the value n). When you want to call do_n, you do it like this:

do_n(countdown, 3)

Not like

do_n(countdown(3), 3) # badness

That last one calls countdown and then calls do_n with its result.

tdelaney
  • 73,364
  • 6
  • 83
  • 116
0
def print_n(s,n):
    if n<=0:
        return
    else:
        print(s)
        print_n(s,n-1)

def do_n(f,s,n,x):
    if x<=0:
        return
    else:
        f(s,n)
        do_n(f,s,n,x-1)

do_n(print_n,'Hello',2,2)
0

It's a tricky one.

Basically, the solution is:

def do_n(f, n):
    if n <= 0:
        return
    f(n)
    do_n(f, n-1)

However, if you actually try combining it with print_n then all hell breaks loose.

First of all, we have to add one more argument, s, to the above code to be able to pass any string that we want to print out n times.

Second of all, the above do_n should be able to repeat any passed function n times so long as the function doesn't mess with do_n. Unfortunately, this is exactly what happens here.

The assignment from the book seems clear: "...write a function called do_n that takes a function object and a number, n, as arguments, and that calls the given function n times..." or in other words do_n calls any function passed to it n times. You'd think if we pass s = 'Hello' and n = 3 then do_n(f, s, n) should output 'Hello' 9 times... because print_n('Hello', 3) prints 'Hello' 3 times and do_n(print_n, 'Hello', 3) is supposed to triple that result... gotcha.

What actually happens is in the first instance of recursion do_n does indeed print out 'Hello' 3 times, because print_n says so. But in the next instance do_n prints out 'Hello' only two times, because it has subtracted 3-1 in the previous instance and now print_n('Hello', 2). In the last instance do_n prints 'Hello' only once, for the same reason. So the total amount of 'Hello' output is 6.

Finally, if you use FOR LOOP instead of recursion to define do_n, you will actually get the correct result of 9 outputs:

def print_n(s, n):
    if n <= 0:
        return
    print(s)
    print_n(s, n-1)

def do_n(f, s, n):
    for i in range(n):
        f(s, n)

do_n(print_n, 'Hello', 3)

P.S. On Page 52 of Think Python 2E we are encouraged to use recursion over for loop:

"For simple examples like this, it is probably easier to use a for loop. But we will see examples later that are hard to write with a for loop and easy to write with recursion, so it is good to start early."

However, in this particular exercise, using recursion forces an output which clashes with the assignment, seeing that do_n and print_n are at odds with each other because constructing do_n with the help of recursion wrongly reduces n in each instance.

Did I get it right?