Approximate overview
(define play-seven-eleven
(lambda ()
(cond
[(= 7 (pair-a-dice))
1]
[(= 11 (pair-a-dice))
1]
[else
0])))
(define pair-a-dice
(lambda ()
(+ (roll-a-die) (roll-a-die))))
(define roll-a-die
(lambda ()
(random 1 7)))
(define count-wins
(lambda (n)
(cond
; No games -> No wins
[(zero? n)
0]
; We win (-: Count it and move on
[(= (play-seven-eleven) 1)
(+ 1 (count-wins (- n 1)))]
; We lose )-: Just move on
[(= (play-seven-eleven) 0)
(count-wins (- n 1))]
; ??? This should never happen
[else
(error "Tie!")])))
The problem: If we lose in the =1 block, we play again. We could win that second time. In that case, we fall to the else. (We’ve also played one more game than we should.)
if statement.let in which we set the variable equal to (play-seven-eleven)(define count-wins
(lambda (n)
(if (zero? n)
0
(+ (play-seven-eleven)
(count-wins (- n 1))))))
8/36 rolls win. So when we play a lot of games, we should win about 8/36 of the time. If we play 3600 games, we should win approximately 800 times. Do we?
Nope.
It’s because we’re calling (pair-a-dice) twice.
random neither too few nor too many times.pair-a-dice is one of the best procedure names ever.;;; (random-list-element lst) -> any?
;;; lst : listof any?
;;; Randomly select an element of `lst`
(define random-list-element
(lambda (lst)
(list-ref lst (random (length lst)))))
;;; people -> listof string?
;;; A list of some of the folks who teach 151
(define people (list "Peter-Michael" "Nicole" "Sarah" "SamR" "Barbara" "Priscilla" "Jerod"))
;;; (random-person) -> string?
;;; Randomly select an element of the people list.
(define random-person
(lambda ()
(random-list-element people)))
Why does random-person have a lambda with no parameters?
Why not write
(define random-person
(random-list-element people))
If we do the
definewithout the lambda, we’ll get the same value every time. We also won’t have a procedure.
Moral: We use empty lambdas when we want procedures to run, which is necessary for random output.
Our goal: Generate some interesting language (Haiku and Templated Writing).
Consider the following procedures
;;; (vowel? char) -> boolean
;;; char : char?
;;; Determine if char is a vowel.
(define vowel?
(let ([vowels (string->list "aeiou")])
(lambda (ch)
(integer? (index-of vowels (char-downcase ch))))))
;;; (count-vowels str) -> integer?
;;; str : string?
;;; Count the number of vowels in str
(define count-vowels
(lambda (str)
(tally vowel? (string->list str))))
;;; (select-special-words words) -> list-of string?
;;; words : list-of string?
;;; Selects all the special words in words using the ALTV criterion.
(define select-special-words
(lambda (words)
(filter (o (section > <> 2) count-vowels) words)))
> (select-special-words '("Um" "banana" "apple" "orange" "pizza" "grape" "coal" "no"))
'("banana" "orange")
a. What kinds of words does select-special-words select?
Words with more than two vowels. (ATLV is “at least three vowels”)
b. Explain how (o (section > <> 2) count-vowels) works as a
predicate for such words.
filterexpects a predicate. The(o (section > <> 2) count-vowels)gets applied to each element in the list. So it first counts the vowels, and then checks if it’s greater than two.
c. Rewrite vowel? using section and composition but no
lambda.
(define vowel?
(let ([vowels (string->list "aeiou")])
(lambda (ch)
(integer? (index-of vowels (char-downcase ch))))))
Hint: Think about the sequence of operations, use o. (o goes
right to left.)
(define vowel?
(let ([vowels (string->list "aeiou")])
(o integer? (section index-of vowels <>) char-downcase))
Why does char-downcase get used?
(o f g)is a shorthand for(lambda (x) (f (g x)))
Our
ois(lambda (x) (integer? ((section index-of vowels <>) (char-downcase x))))
(section f val <>)is a shorhand for(lambda (y) (f val y)). Maybe that’s not relevant here.
You are unlikely to receive a problem this hard.
Consider the following procedure.
(define silly
(lambda (lst)
(map (lambda (x) (sqr (+ 1 x)))
(filter odd? lst))))
Rewrite the procedure using o and section so that it has no lambdas.
(lambda (x) (sqr (+ 1 x))) is “a procedure that adds one and
then squares. We can rewrite it as (o sqr (section + 1 <>))(define silly
(o (section map (o sqr (section + 1 <>)) <>)
(section filter odd? <>)))
With the diamonds, how do you know which parameters they take?
Careful analysis.
The last diamond is “the input to the procedure”
Because I have composition, I know that the penultimate diamond is “the output from filter”.
The first diamond is used in
map, so I know that it’s going to be used for every element in some list (that list is the output from filter)