University of California, Berkeley
EECS Department - Computer Science Division
CS3 Lecture 7 : Recursion and Patterns
Thanks to Oliver Grillmeyer and Brendan Ferguson for
many of the ideas for these notes
Overview of today's lecture
Answers to questions
that have come up
- Why is the base case for nothing-but-a-words?
#t?
- Answer #1 : We'll see the reasons for this when we look at
other testing functions
- If we changed the name of the function to no-non-a-words?,
would that be ok? That's what we're computing.
Review
Recursion
An algorithmic technique where a function, in order
to accomplish a task, calls itself with some part of the task.
- Recursive solutions involve two major parts:
- Base case(s), in which the problem is simple enough
to be solved directly,
- Recursive case(s). A recursive case has three components:
- Divide the problem into one or more simpler or smaller
parts of the problems,
- Invoke the function (recursively) on each part, and
- Combine the solutions of the parts into a solution
for the problem.
- Depending on the problem, any of these may be trivial or
complex.
Example problems we saw
- my-count, which calculates the length of a sentence
- nothing-but-a-words?, which returns #t
if a sentence has nothing but a-words
Recursion doesn't have to be limited
to sentence manipulation, consider sum-0-to-n
- Don't think recursion is only applied to sentences.
- The emphasis on sentences (and words) is because they're
the only data structure we've got! (so far)
- How about this problem: consider summing all the numbers
from 0 to n
;; sum-0-to-n
;;
;; INPUTS : A positive integer, n
;; REQUIRES : The input be a positive integer
;; SIDE-EFFECTS : None
;; RETURNS : The sum of all numbers from 0 to n.
;; EXAMPLE : (sum-0-to-n 1) ==> 1
;; : (sum-0-to-n 5) ==> 15 ;; 1+2+3+4+5=15
(define (sum-0-to-n n)
==>
==>
==>
: (sum-0-to-n 0)
==>
: (sum-0-to-n 5)
==>
: (sum-0-to-n -1) ;; violates our requirement
==>
- What just happened? ==>
- What does that tell us about our base cases? ==>
Recursion and Patterns
Overview
- One of the things we'll notice is that there are recurring
patterns when we write our recursive programs
- We'll see the following main patterns for recursive programs:
Powerful sentence functions we've seen
- member?
- count
- accumulate
- every
- keep
- repeated
Recursive patterns we'll see on sentences
- Mapping (e.g., every)
- Takes a sentence and does something to every element in the
sentence and returns a sentence of the same size
- e.g., square-all, square all numbers in a sentence
- Finding (like member?)
- Finding the first element of a sentence that satisfies test,
and return either that element or the rest of the sentence starting
with that element, #f otherwise.
- e.g., member-even, return the rest of the sentence
starting with the first even number, #f ottherwise.
- Counting (like count)
- Counting the number of elements that satisfy a test
- e.g., count-evens, return the number of even numbers
in a sentence
- e.g., my-count, which returns the number of words
in the sentence
- Filtering (like keep)
- Takes a sentence and for each element, decides to either
keep or discard it.
- e.g., remove-evens, remove all the even numbers
in a sentence
- e.g., keep-ones, which returns a sentence of the
ones in the sentence
- Testing (like all?)
- Predicate which checks something about every or any
element of the sentence, returns whether it's true or not
- e.g., all-evens? which returns #t if all numbers
are even
- Combining (like accumulate)
- Combine the elements of the sentence in some way
- e.g., get-min, which gets the minimum element
- e.g., sentence-sum, which returns the sum of the
elements in a numeric sentence
Mapping Example : square-all
;; square-all
;;
;; INPUTS : A sentence of numbers
;; REQUIRES : The input be a simple linear sentence of numbers
;; SIDE-EFFECTS : None
;; RETURNS : A sentence of the same size as the input, but with
;; : all elements squared.
;; EXAMPLE : (square-all '()) ==> ()
;; : (square-all '(1 2 3 4)) ==> (1 4 9 16)
: (define (square x) (* x x))
square
(define (square-all L)
==>
==>
==>
: (square-all '())
==>
: (square-all '(1 2 3 4))
==>
Finding Example : member-even
;; member-even
;;
;; INPUTS : A sentence of numbers
;; REQUIRES : The input be a simple linear sentence of numbers
;; SIDE-EFFECTS : None
;; RETURNS : The rest of the sentence starting with the first even #
;; : and #f if none exists (just like member would have)
;; EXAMPLE : (member-even '()) ==> #f
;; : (member-even '(1 2 3 4)) ==> (2 3 4)
;; : (member-even '(1 3 5 7)) ==> #f
(define (member-even L)
==>
==>
==>
: (member-even '())
==>
: (member-even '(1 2 3 4))
==>
: (member-even '(1 3 5 7))
==>
Counting Example : count-evens
;; count-evens
;;
;; INPUTS : A sentence of numbers
;; REQUIRES : The input be a simple linear sentence of numbers
;; SIDE-EFFECTS : None
;; RETURNS : The number of even numbers in the sentence
;; EXAMPLE : (count-evens '()) ==> 0
;; : (count-evens '(1 2 3 4)) ==> 2
;; : (count-evens '(2 4 6 8)) ==> 4
;; : (count-evens '(1 3 5 7)) ==> 0
(define (count-evens L)
==>
==>
==>
==>
: (count-evens '())
==>
: (count-evens '(1 2 3 4))
==>
: (count-evens '(2 4 6 8))
==>
: (count-evens '(1 3 5 7))
==>
Filtering Example : remove-evens
;; remove-evens
;;
;; INPUTS : A sentence of numbers
;; REQUIRES : The input be a simple linear sentence of numbers
;; SIDE-EFFECTS : None
;; RETURNS : The sentence with the even numbers removed
;; EXAMPLE : (remove-evens '()) ==> ()
;; : (remove-evens '(1 2 3 4)) ==> (1 3)
;; : (remove-evens '(2 4 6 8)) ==> ()
;; : (remove-evens '(1 3 5 7)) ==> (1 3 5 7)
(define (remove-evens L)
==>
==>
==>
==>
==>
: (remove-evens '())
==>
: (remove-evens '(1 2 3 4))
==>
: (remove-evens '(2 4 6 8))
==>
: (remove-evens '(1 3 5 7))
==>
Testing Example : all-evens?
;; all-evens? (can also be thought of as (not (any-odds? L)) )
;;
;; INPUTS : A sentence of numbers
;; REQUIRES : The input be a simple linear sentence of numbers
;; SIDE-EFFECTS : None
;; RETURNS : #t if the entire sentence is even, #f otherwise
;; : This can also be thought of as (not (any-odds? L))
;; EXAMPLE : (all-evens? '()) ==> #t
;; : (all-evens? '(1 2 3 4)) ==> #f
;; : (all-evens? '(2 4 6 8)) ==> #t
;; : (all-evens? '(1 3 5 7)) ==> #f
(define (all-evens? L)
==>
==>
==>
==>
: (all-evens? '())
==>
: (all-evens? '(1 2 4 8))
==>
: (all-evens? '(2 4 6 8))
==>
: (all-evens? '(1 3 5 7))
==>
Combining Example : get-min
;; get-min
;;
;; INPUTS : A sentence of numbers
;; REQUIRES : The input be a simple linear sentence of numbers
;; : The sentence have length at least one (min of nothing undefined)
;; SIDE-EFFECTS : None
;; RETURNS : The minimum element in the sentence
;; EXAMPLE : (get-min '(795)) ==> 795
;; : (get-min '(3 1 4 1)) ==> 1
(define (get-min L)
==>
==>
==>
: (get-min '(795))
==>
: (get-min '(3 1 4 1))
==>
: (get-min '()) ;; This violates our requirements
==>
Summary
- We saw lots of examples of recursion, and hopefully some
patterns we highlighted started to sink in.
Next Time
- We'll look at (surprise, surprise) even more examples of
recursion
Puzzle : Scrambled box tops [Martin Gardner
"My Best Mathematical and Logic Puzzles", Dover Press,
1994]
- Imagine that you have three boxes, one containing two black
marbles, one containing two white marbles, and the third, one
black marble and one white marble.
- The boxes were labeled for their contents -- BB, WW, and
BW -- but someone has switched the labels so that every box
is now incorrectly labeled.
- You are allowed to take one marble at a time from any box,
without looking inside, and by this process of sampling you are
to determine the contents of all three boxes.
- What is the smallest number of drawings needed to do this,
and how is it done?
Game : Take numbers from the ends [David
Ginat, Tel-Aviv University]
- The game begins with a line of numbers, like [10 5 7 88 1
-5]
- The number of numbers is even.
- Players take turns removing numbers from the ends and keeping
a personal running total of the amount collected so far.
- The player with the largest sum at the end wins.
WWW Maven: Dan
Garcia (ddgarcia@cs.berkeley.edu)
Send me feedback