[Tutor] A small (but long) introduction to recursion

Kevin McCormick kev@sat.net
Wed, 25 Jul 2001 10:06:19 -0500


Danny Yoo wrote:
> 
> I wrote this up today for a student in an introductory CS class; I thought
> it might be interesting for people on tutor, so here's a version of the
> introduction in Python.
> 
> [warning: this is a somewhat long message.]
> 
> ---
> 
> Here's an example of a "recursive" problem:  Let's say that we're trying
> to add up the numbers:
> 
>     0 + 1 + 2 + ... + n
> 
> together.  In Python, this is pretty easy:
> 
> ###
> ## non-recursive version of addUpToN
> def addUpToN(n):
>     """Adds the numbers from zero to n, inclusive.  1 + 2 + ... + n"""
>     sum = 0
>     for i in range(n+1):
>         sum += i
>     return sum
> ###
> 
> And since it's so "easy" to define, let's make sure it works:
> 
> ###
> >>> addUpToN(0)
> 0
> >>> addUpToN(1)
> 1
> >>> addUpToN(2)
> 3
> >>> addUpToN(3)
> 6
> >>> addUpToN(10)
> 55
> >>> 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10
> 55
> >>> reduce(lambda x, y: x + y, range(11))   # just playing around...
> 55
> ##
> 
> Ok, it looks good.  (Note: the first time I did this, I was off by a lot
> by accidently doing "range(n)" instead of "range(n+1)".  Testing code is a
> very good idea.  *grin*)
> 
> However, there's a "recursive" way to view this problem, a way of
> boomeranging the problem around itself: to add the numbers from 0 to n, we
> can add the numbers from 0 to n-1.  Once we have that, we can finish the
> sum by adding 'n'.  What we mean is that:
> 
> ###
> def addUpToNRecursive(n):
>     if n == 0: return 0
>     return addUpToNRecursive(n-1) + n
> ###
> 
> Let's test it out.
> 
> ###
> >>> addUpToNRecursive(0)
> 0
> >>> addUpToNRecursive(1)
> 1
> >>> addUpToNRecursive(2)
> 3
> >>> addUpToNRecursive(10)
> 55
> ###
> 
> When we think about recursive solutions to problems, we try to figure out
> a way of teasing out a smaller piece to help us out.  The part that
> actually does the brunt of the work is this line:
> 
>     return addUpToNRecursive(n-1) + n
> 
> What we're telling Python is that: "To add (1 + 2 + 3 + .... + n), all we
> need to do is add (1 + 2 + 3 + ... + n-1), and top it off with 'n'."
> It's very neat and short.  In technical terms, this is called the
> "recursive step" --- the part that depends on a call to itself.
> 
> The line right before, though,
> 
>     if n == 0: return 0
> 
> seems a bit arbitrary, no?  What happens if we pull it out?
> 
> ###
> def addUpToNBrokenRecursive(n):
>     return addUpToNBrokenRecursive(n-1) + n
> ###
> 
> The name gives a hint, but how is it "broken"?  Let's try it out:
> 
> ###
> >>> addUpToNBrokenRecursive(0)
> Traceback (most recent call last):
>   File "<stdin>", line 1, in ?
>   File "/usr/tmp/python-6609I5e", line 14, in addUpToNBrokenRecursive
>   File "/usr/tmp/python-6609I5e", line 14, in addUpToNBrokenRecursive
>   ... [lots and lots of lines later]
>   File "/usr/tmp/python-6609I5e", line 14, in addUpToNBrokenRecursive
> RuntimeError: maximum recursion depth exceeded
> ###
> 
> Wow.  This is akin to the "Are we there yet?" game that children use to
> gleefully madden their parents.
> 
>     "Are we there yet?"
>     "No."
>     "Are we there yet?"
>     "No."
>     "Are we there yet?"
>     "No!"
> 
> Unlike the road game, the road goes on and on in a recursion that doesn't
> say when to stop.  In addUpToNBrokenRecursive(),
> 
> ###
> def addUpToNBrokenRecursive(n):
>     return addUpToNBrokenRecursive(n-1) + n
> ###
> 
> what's missing is a "base case", something that the function is absolutely
> sure it knows how to answer without calling itself.  It needs a solid
> foundation, and that's the role that the line,
> 
>     if n == 0: return 0
> 
> plays.  Of course, if we pass something like -1 off to the function, we'll
> fall off the edge of the world again... But as long as we decide that
> 'n' needs to be >= 0, that's ok.
> 
> (Anyway, what does it even mean to do "0 + 1 + ... + -42"?)
> 
> Anyway, better stop here.  If you have any questions, feel free to email
> the tutor list.  If anyone requests it, we can show more examples of
> recursion.  Not everything molds well to a recursive solution, but in some
> cases, it's a beautiful approach.
> 
> Hope this helps!
> 
> _______________________________________________
> Tutor maillist  -  Tutor@python.org
> http://mail.python.org/mailman/listinfo/tutor

I absolutely do not understand recursion. I took your example and tried
to do some tracing, but I do not understand how the sum is stored or
returned:

def addUpToNRecursive(n):
    if n == 0: return 0
    print n
    return addUpToNRecursive(n-1) + n

x = addUpToNRecursive(10)
print x