Laboratory Exercises For Computer Science 151

Deep Recursion

Deep Recursion

Consider the list

   (((a b) c) d (e (g)))
At the top level, this list has three components, ((a b) c), d, and (e (f)). If we look within these components, we find there are a total of six symbols (the letters a through g). To count or otherwise process these symbols, procedures must work within sublists as well as working within the top level of the main list. As we have seen consistently, procedures in Scheme typically work recursively. Here, such procedures must apply recursion to components of lists as well as to the top-level components. Such processing is called deep recursion.

Goals: This laboratory exercise describes an example of deep recursion and provides experience applying this technique to several more examples.

Preparation: Reread section 4.3 of the textbook.

Example: Consider the problem to count the number of times a given symbol appears in a list or any of its sublists. If this task were performed by procedure count-symbol, then this procedure should give the following results:


   (count-symbol 'a '(((a b) c) a (a (b)))) ===> 3
   (count-symbol 'b '(((a b) c) a (a (b)))) ===> 2
   (count-symbol 'd '(((a b) c) a (a (b)))) ===> 0
To attack this problem, we first identify an easy case: the empty list does not contain any symbol. This observation prompts the first part of some code for count-symbol:

   (define count-symbol
       (lambda (symbol ls)
           (cond ((null? ls) 0)
                 ;;; further conditions to be determined
           )
       )
   )
If we do not encounter a null list, then it is possible to follow several approaches. In one such approach, there are two main cases: This approach gives rise to the following code:

 (define count-symbol
     (lambda (symbol ls)
         (cond ((null? ls) 0)
               ((list? (car ls)) (+ (count-symbol symbol (car ls)) 
                              (count-symbol symbol (cdr ls))))
               ((eq? symbol (car ls)) (+ 1 (count-symbol symbol (cdr ls))))
               (else (count-symbol symbol (cdr ls)))
         )
     )
 )

Steps for this Lab:

  1. Run count-symbol on the lists shown in the above three examples. In each case, trace execution to explain how the result is obtained.

  2. Describe what the following procedure does:
    
      (define question-2
          (lambda (ls)
              (cond ((null? ls) #t)
                    ((list? (car ls)) (and (question-2 (car ls))
                                           (question-2 (cdr ls))))
                    ((number? (car ls)) (question-2 (cdr ls)))
                    (else #f)
              )
          )
      )
    

  3. Write a procedure all-to-zero that changes all numbers in a list or in any components of the list to 0 but leaves all other elements unchanged. For example,
    (all-to-zero '(7 (a (1/2 b) 3.14159) ((c -9)))) should return
    (0 (a (0 b) 0) ((c 0))).

  4. Textbook Exercises: Solve exercises 4.5-4.7 from the textbook.
Work To Turn In:


This document is available on the World Wide Web as

http://www.math.grin.edu/~walker/courses/151.fa99/lab-deep-recursion.html

created February 13, 1997
last revised September 28, 1999