CS30 - Spring 2016 - Class 10
Example code in this lecture
recursion.py
turtle_recursion.py
Lecture notes
administrative
- assignment 4
- due Friday at 6pm
midterm next Tuesday
- Will cover everything up through today
- recursion will be covered, but at a high-level since you haven't done an assignment on it 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
- I put a dot here just do make it explicit
- we could have also just done nothing if we wanted
- 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