CSC 151.01, Class 17: Recursion basics
Overview
- Preliminaries
- Notes and news
- Upcoming work
- Extra credit
- Questions
- Background
- Key ideas in recursion
- Sample recursive procedures
- Expressing recursion in Scheme
- Lab
News / Etc.
- New partners.
- Please make sure to return your computer cards to the jar.
- Exam 1 returned last night. I’m happy to take questions via email or during office hours. (I’ll probably add some office hours this week.)
- I have not had time to grade your quizzes. You may get them back on Wednesday (but you may not).
- Dates in formats like “10/02/2017” are ambiguous. Dates like “10/02/17” are even worse. Please use “YYYY-MM-DD” format for your dates.
- Please discuss which switching format you and your partner will use
- Switch every ten minutes
- Switch midway through class
- Switch every problem
- We will have some discussion at the start of today’s class.
Upcoming Work
- No writeup for class 16.
- Writeup for class 17 due Wednesday at 10:30 p.m.
- Exercises TBD
- To: csc151-01-grader@grinnell.edu
- Subject: CSC 151.01 Writeup 17 (YOUR NAMES)
- Assignment 5 due Tuesday at 10:30 p.m.
- Reading for Wednesday’s class: Recursion with helper procedures
- Should be ready tonight
Extra credit (Academic/Artistic)
- Any of the many Grinnell Prize events.
- Wednesday, 5pm, Mary Beth Tinker Talk
- CS Table, Tuesday: Tapia.
Extra credit (Peer)
- Volleyball vs. Knox Tuesday at 7:00 p.m.
- Men’s Soccer Wednesday at 4:30 vs. Cornell
- Volleyball vs. Beloit, Friday at 7:00 p.m.
- Women’s Tennis vs. St. Norbert, Saturday at 9:00 a.m.
- Volleyball vs. Lake Forest, Saturday at 1:00 p.m.
- Women’s Tennis vs. Ripon, Saturday at 3:00 p.m.
- Nice Fish. This weekend. Say “Ooh, Aah, Impressive” at the well placed lights.
Other good things
- Football, Saturday at 1:00 p.m.
Questions
- Can you help on problem 3?
- Sure.
- Your goal is to find nearby words.
- As we suggested in the assignment, the first step should be to make lists of nearby words.
- Suppose our original text was
'("twas" "brillig" "and" "the" "slithy" "toves" "did" "gyre") - We will make three “successor lists” of equal length.
'("brillig" "and" "the" "slithy" "toves" "did" "gyre" "")'("and" "the" "slithy" "toves" "did" "gyre" "" "")'("the" "slithy" "toves" "did" "gyre" "" "" "")
- We can use
mapto combine them together - We can use
filterto extract all of the lines that begin with a certain word - We can use some clever combination of operations to put them back together.
- Can we have repeated elements in the list?
- Yes. You’ll find that useful for problem 4.
- Is it okay if the labels on our histogram for problem 5 overlap?
- Yes.
- What’s that mantra again?
- I’m still working on it.
- “Solve for one or two, then for all.”
- Stay tuned for the JS version.
- I’m struggling. I feel like it’s only me.
- It’s not. We’re doing hard stuff. But historical evidence suggests that you will make it.
- Do we really get the next exam on Wednesday?
- Yes.
- How do I figure out how many pages are in a book?
- That’s a good question. I’d look for it on Google books or Amazon and see what they say.
- 100K to 200K words is appropriate. (K is short for Kilo and can mean 1000 or 1024.)
Background
There are six or so things that go into algorithms
- Input and output
- Basic building blocks - Things provided by the language (or by libraries)
E.g.,
squareis provided bycsc151and+is provided by Scheme. - Repetition - Doing things again and again and again. We can repeatedly
transform elements with
map. - Subroutines - Something you can do again and again. A collection of
instructions that you can refer to by name. We can use
definewithlambdaorosomething else to create such collections. (Scheme’s procedures are subroutines.) - Sequencing - We should know/specify the order in which things are computed
when that order matters. Parentheses - Inside out.
odoes its procedures right-to-left,andevaluates its arguments left to right,let*does the name/exp bindings in order, … - Conditionals - Take a condition; if it’s satisfied, do one thing,
if not, do something else. (Plus variants.)
if,cond,when. - Names (variables) - We can associate names with values. Use
defineorletorlet*.
We have all the tools we need. But our forms of repetition are limited. We only know how to repeat with lists, and only in certain forms.
In Scheme (and every programming language) one of the key mechanisms for repetition is recursion.
We will explore a variety of problems of repetition.
To count how many elements there are in a list If you have only one element say “one” Otherwise Remove one piece Have someone else count the remaining things Add 1 to that result
To determine how many words contain the letter “a”. Assume that you can tell by inspection whether or not a word contains the letter “a”
(define contains-a?
(lambda (word)
(>= (index-of #\a (string->list word)) 0)))
To count how many elements in a list contain a If you have only one element and it contains a say “one” Otherwise, if you have only one element and it does not contain a say “zero” Otherwise Remove one piece Have someone else count the number of remaining things that contain a If the thing you removed contains a, add 1 Otherwise, return the same value
To filter elements in a list that contain a If you have only one element and it contains a give back that element (list of that element) Otherwise, if you have only one element and it does not contain a give back nothing (empty list) Otherwise Remove one piece Have someone else filter the number of remaining things that contain a If the thing you removed contains a, add name (cons) Otherwise, return the same value
(define contains-a?
(lambda (word)
(>= (index-of #\a (string->list word)) 0)))
(define filter-as
(lambda (lst)
(cond
; If you have only one element and it contains a
[(and (contains-a? (car lst)) (= (length lst) 1))
; Give back the same thing
lst]
; If you have only one element and it does not contain a
[(= (length lst) 1)
; Give back nothing
null]
; Otherwise
[else
; Remove one piece - cdr
; Do the same thing again - filter as
(let ([remaining-stuff (filter-as (cdr lst))])
; If the thing you removed contains a, cons the thing back
(if (contains-a? (car lst))
(cons (car lst) remaining-stuff)
; Otherwise, just return what you got back
remaining-stuff))])))
Perhaps we want to deal with the empty list.
(define filter-As
(lambda (lst)
(cond
[(null? lst)
null]
[else
(let ([remaining-stuff (filter-As (cdr lst))])
; If the thing you removed contains a, cons the thing back
(if (contains-a? (car lst))
(cons (car lst) remaining-stuff)
; Otherwise, just return what you got back
remaining-stuff))])))
Oooh! It’s shorter and it works with the null list.
It’s also faster.
To check if a list has only one item use (null? (cdr lst))
or (and (not (null? lst)) (null? (cdr lst)))
Key ideas in recursion
- Big idea: You can solve a big problem by solving a smaller instance
of the same problem and then “tacking on” a bit more.
- Recursive case
- Medium idea; At some point, you have to stop delegating. “Base case
check” and “base case result”
( You can have more than one - Side idea: Sometimes you have multiple recursive cases and base cases