CS30 - Spring 2015 - Class 10

Example code in this lecture

   recursion.py
   turtle_recursion.py

Lecture notes

  • administrative
       - assignment 4
          - due Friday at 6pm
          - One of the more challenging assignments
       - assignment 2 pictures posted

  • midterm next Thursday
       - Will cover everything up through today
          - recursion will be covered, but at a high-level since you haven't done an assignment yet
       - Different types of questions
          - T/F (on coding)
          - Short answer, e.g.
             - what does this code do?
             - what's wrong with this code?
             - ...
          - Coding: write a function that does X
             - practice writing code on paper
       - What you can use:
          - your brain :)
          - up to 2 pages (single-sided, or 1 page double-sided) of notes (in a reasonable font)

  • google "recursion"

  • the four steps to writing a recursive function:
       1. define what the function header is
       2. define the recursive case
       3. define the base case
       4. put it all together

  • write a function called power that takes a base and an exponent and returns base^exponent (i.e. the same thing as '**' without using '**')
       - you can assume that exponent >= 0

       1. define what the function header is
          def power(base, exponent)

       2. define the recursive case
          b^e = b * b^(e-1)

          - we can define the power function as the power function of the exponent - 1 times the base

       3. define the base case
          - each time the exponent is getting smaller
          - eventually, the exponent will be 0
             - b^0 = 1

       4. look at the power function in recursion.py code
          - check the base case when the exponent == 0
             - in this case just return 1
          - otherwise, do the recursive case
             - base * power(base, exponent-1)

       - how many times is power called?
          - exponent+1 times
             - power(base, exponent)
             - power(base, exponent-1)
             - power(base, exponent-2)
             - ...
             - power(base, 1)
             - power(base, 0)

       - can we do any better efficiency-wise (that is, less calls to exponent)?
       - look at fast_power function in recursion.py code
          - two different recursive cases
             - if the exponent is even
                - b^e = b^(e/2) * b^(e/2)
             - if the exponent is odd
                - our normal recursive case
                - b^e = b * b^(e-1)
          - why is this faster?
             - when it's even, instead of just decreasing by 1, we decrease by a half!

  • look at the spiral function in turtle_recursion.py code
       - for example, what would the picture look like if I called:
          >>> spiral(80, 50)
       - what does this function do?
          - recursive function
          - draws a spiral on the screen
             - forward 80
             - left 30
             - spiral( 76, 49 )
                - forward 76
                - left 30
                - spiral(72.2, 48)
                   - forward 72.2
                   - left 30
                   - ...
          - when does it stop?
             - when levels == 0
          - repeat 50 times:
             - forward length
             - left 30
             - reduce length by 5%

       - what if we wanted to end up back at the starting point, but we couldn't pick the pen up?
          - one way would be to trace our steps backward
          - Assume that the recursive call returns back to its starting point. What would we need to do to make sure that our call returned back to the starting point?
             - Add the following after the recursive call:

                right(30)
                backward(length)

          - if we run it now, we draw the spiral all the way down, and then we retrace backwards
       - why does this work?
          - each call to spiral retraces its own part after the recursive call
          - the stack keeps track of each of the recursive calls

  • run broccoli_demo function in turtle_recursion.py code
       1. define what the function header is
          - broccoli(x, y, length, angle)

       2. define the recursive case
          - broccoli is a line with three other broccolis at the end
             - one directly straight out
             - one 20 degrees to the left
             - one 20 degrees to the right
          - the three other broccolis should be smaller/shorter than the current

       3. define the base case
          - eventually the length of the broccoli to be drawn gets too short
          - at that point instead of recursing, we draw a yellow dot at the end and stop recursing

       4. put it all together
          - look at broccoli function in turtle_recursion.py code
             - draw a line in the direction specified
             - check the base case
                - if the line length is less than 10, just put a yellow dot at the end
             - otherwise, it's the recursive case
                - draw three smaller broccolis at different angles

             - what are new_x and new_y?
                - the ending coordinates of the line being drawn
             - why do we need to save them?
                - after the first recursive call to broccoli the turtle won't be in the same place

       - if we turn tracing back on, what will we see, that is, what order will it draw in?
          - going to go right (angle -20) over and over again until it gets too short
             - it will end the recursion then draw a short center
             - this also will be a base case and draw the left
          - then it will start to work it's way back up
          - eventually, it will make it back up to the top-level and start drawing the center stalk
          - after drawing the center stalk, it will draw the left stalk