- Write a structurally recursive function named
(tree-count test? tree) that takes as arguments
a function test? and a binary tree tree of
this form:
<binary-tree> ::= <number>
| (<number> <binary-tree> <binary-tree>)
tree-count returns the number of values in the tree that
satisfy test?, a one-argument function. For example:
> (tree-count positive? '(1 (2 3 4) 5)) ; all five are positive
5
> (tree-count (lambda (n) (> n 10)) ; nodes bigger than 10
'(8 (13 11 (5 24 6)) (15 (12 10 14) 20)))
7
Note: tree-count does not need an extra
parameter to solve this problem! Use regular structural
recursion.
- Write a mutually recursive procedure
(annotate exp), which takes a prefix binary
expression as an argument.
<prefix-exp> ::= (<operator> <number-exp> <number-exp>)
<number-exp> ::= <number>
| <prefix-exp>
annotate returns an expression of the same form, with the
operator op replaced by the pair (op . level).
level records the 0-based depth of the operation in the
tree. For example:
> (annotate '(+ 4 5))
'((+ . 0) 4 5)
> (annotate '(* (+ 4 5)
(/ 7 6)))
'((* . 0) ((+ . 1) 4 5)
((/ . 1) 7 6))
> (annotate '(* (+ 4 5)
(/ 7 (+ 6 5))))
'((* . 0) ((+ . 1) 4 5)
((/ . 1) 7 ((+ . 2) 6 5)))
Make annotate
an interface procedure
that calls a structurally recursive helper function with two
arguments: the expression and an initial value for the level
counter.
annotate must be mutually recursive with the
function (annotate-ne num-exp level), which
annotates number expressions.
- Answer very briefly the following questions.
One sentence or Racket expression is sufficient for each.
- How does program derivation improve the efficiency
of a mutually-recursive solution?
- This version of the factorial function is
tail recursive:
(define factorial
(lambda (n acc)
(if (zero? n)
acc
(factorial (sub1 n) (* n acc)))))
What does that statement mean, in terms of the way the
function executes at run time?
- A number can be defined inductively as a sequence of
digits:
<digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
<number> ::= <digit>
| (10 * <number>) + <digit>
Write the framework of the if (or cond)
expression that will be the main control structure of any
structurally-recursive function that processes numbers of
this form. Use comments for the 'then' and 'else'
clauses to show the cases they handle.
- The expression
(occurs-free? x exp)
is not always equal to the expression
(not (occurs-bound? x exp))
for a given x and exp.
Give an example that illustrates why.
Extra Credit. There are two ways in which
this is true. Give distinct examples that illustrate
both ways.
- Write a mutually-recursive function
(slist-contains? s slst) that takes two arguments,
a symbol s and an s-list slst:
<s-list> ::= ()
| (<symbol-expression> . <s-list>)
<symbol-expression> ::= <symbol>
| <s-list>
slist-contains? returns true if s appears
anywhere in slst, and false otherwise. For example:
> (slist-contains? 'eugene '((a b) (((b g r) (f r)) c (d e)) b))
#f
> (slist-contains? '/ '(if (zero? n) zero (/ total n)))
#t
slist-contains? must be mutually recursive with
the function symexp-contains?, which determines if
a symbol appears anywhere in a symbol expression.
- Write a structurally recursive function
(contains-varref? v exp) that takes two arguments:
a symbol v and an expression exp in our little
language:
<exp> ::= <varref>
| (lambda (<var>) <exp>)
| (<exp> <exp>)
contains-varref? returns true if v is
used as a variable reference anywhere in exp, and false
otherwise. For example:
> (contains-varref? 'y 'y)
#t
> (contains-varref? 'x '(lambda (x) x))
#t
> (contains-varref? 'y '(lambda (y) x))
#f
> (contains-varref? 'x '(f (lambda (y) x)))
#t
> (contains-varref? 'x '( (lambda (x) y) ; x is not used here
(lambda (y) x) )) ; but x is used here
#t
You must use these syntax procedures for the little
language, as provided in class.
exp?
varref?
lambda? lambda->param lambda->body
app? app->proc app->arg