Quiz 2

Recursive Programming Techniques


CS 3540
Programming Languages and Paradigms
Spring Semester 2023


Tuesday, March 7, 2023 @ 1:05 PM


Instructions



Exercises

  1. 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.

  2. 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.

  3. Answer very briefly the following questions. One sentence or Racket expression is sufficient for each.

  4. 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.

  5. 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
    


Eugene Wallingford ..... wallingf@cs.uni.edu ..... March 6, 2023