Quiz 1 - FT98 - Solutions

         
                   MASSACHVSETTS INSTITVTE OF TECHNOLOGY
         Department of Electrical Engineering and Computer Science
       
         6.001 -- Structure and Interpretation of Computer Programs
                         Quiz 1 --  Fall Term 1998
            Closed book except for one sheet of notes (one side)
     
     Print your name at the top of each page of this exam.  We know this is
     tedious, but prevents problems if the pages get separated.
     
     Please write clear and concise answers to the questions posed in the
     spaces provided in this booklet.  You may use scratch paper if you
     wish, but the spaces provided for the answers are the ONLY places we
     will look at when grading the quiz.  Your answers should be brief and
     clear.  The staff reserves the right to ignore illegible answers.  In
     grading problems that require programming, the staff will take into
     consideration the style and clarity of your code, not just whether it
     happens to produce the right result.  Before starting, please check
     that this booklet has all 11 pages (not counting this cover page, and
     the list processing procedure definitions on the last page which are
     provided for your convenience).
     
     
     
     Print your name here:__Ben Bitdiddle______________________________
     
     
     Print your tutor's name here:__Chuck Vest_________________________
     
     
     Recitation instructor:__William Barton Rogers_____________________
     
     
     If you have any comments about this quiz, please write them here:
     
     
     
     
     
     
     
       Please do not write below this line -- reserved for administrivia.
     _______________________________________________________________________
     
     Problem  Grade   Grader   Prob   Grade   Grader       Grader's Comments
     --------------------------------------------------    -----------------
     | 1    |      |         || 4    |      |         |
     --------------------------------------------------
     | 2    |      |         || 5    |      |         |
     --------------------------------------------------
     | 3    |      |         || 6    |      |         |
     --------------------------------------------------
     --------------------------------------------------
     |                       ||TOTAL |      |         |
     --------------------------------------------------
     
----------------------------------------------------------------------

     
     PROBLEM 1 (10 points)
     
     A. Draw a box and pointer diagram for the value of z after the
     following Scheme code is evaluated.
     
     (define (make-two x)
       (list x x))
     
     (define z (make-two (make-two 3)))
     
ANS:     
     
  The key is to recognize that the first list produced by (make-two 3)
is *shared* in the second list:

     
     B. When z is evaluated, write what the interpreter prints:
     
     z ==>  ANS: ((3 3) (3 3))
     
     
     
----------------------------------------------------------------------
 
     PROBLEM 2 (25 points)
     
       Alyssa, Ben, Carl, and Dan argue that they can improve the
     efficiency of the ENUMERATE-INTERVAL procedure from the book.  Each of
     their procedures (shown on the next page) work correctly.  For each of
     their procedures (as well as the procedure from the book also shown on
     the next page) complete the table below to indicate:
     
     A. Whether the procedure generates an iterative or recursive process.
     
     B. The order of growth in space that the procedure requires (where we
     count the maximum depth of deferred operations) as a function of n,
     where n = hi - lo.
     
     C. The order of growth in time that the procedure requires (where we
     count the total number of CONS operations performed) as a function of n.
     
     Definitions for the APPEND procedure, as well as the list handling
     procedures LENGTH, MAP, ACCUMULATE, and FILTER are provided at the end
     of this quiz handout.
     
     
                        | A. iterative   | B. Space Needed | C. Time Needed |
                        | or recursive?  |     Theta( )    |     Theta( )   |
     ------------------------------------------------------------------------
     enumerate-interval |                |                 |                |
                        | recursive      |       n         |       n        |
                        |                |                 |                |
     ------------------------------------------------------------------------
     alyssa-ei          |                |                 |                |
                        | recursive      |       n         |       n        |
                        |                |                 |                |
     ------------------------------------------------------------------------
     ben-ei             |                |                 |                |
                        | recursive      |       n         |       n        |
                        |                |                 |                |
     ------------------------------------------------------------------------
     carl-ei            |                |                 |                |
                        | iterative      |       1         |       n        |
                        |                |                 |                |
     ------------------------------------------------------------------------
     dan-ei             |                |                 |                |
                        | recursive      |       n         |    n log n     |
                        |                |                 |                |
     ------------------------------------------------------------------------

  The hard one here was dan-ei.  It is order n because the number of
deferred appends is order log_2 n, but when those finally get computed
each append "adds" order n deferred appends.

  In time, append gets called about order log_2 n, and EACH of these
requires order n cons operations.

     
     PROBLEM 2, Continued
     
     
     (define (enumerate-interval lo hi)
       (if (> lo hi)
           nil
           (cons lo (enumerate-interval (+ 1 lo) hi))))
     
     
     
     
     (define (alyssa-ei lo hi)
       (define (helper x)
         (if (> x hi)
             nil
             (cons x (helper (+ 1 x)))))
       (helper lo))
     
     
     
     
     (define (ben-ei lo hi)
       (cond ((= lo hi) (list hi))
             ((> lo hi) nil)
             (else (cons lo
                         (cons (+ 1 lo)
                               (ben-ei (+ 2 lo) hi))))))
     
     
     
     (define (carl-ei lo hi)
       (define (helper x sofar)
         (if (< x lo) 
             sofar
             (helper (- x 1) (cons x sofar))))
       (helper hi nil))
     
     
     
     
     (define (dan-ei lo hi)
       (let ((num (- hi lo)))
         (cond ((> lo hi) nil)
               ((= num 0) (list lo))
               ((odd? num) (cons lo (dan-ei (+ 1 lo) hi)))
               (else (let ((mid (+ lo (/ num 2))))
                       (append (dan-ei lo mid)
                               (dan-ei (+ 1 mid) hi)))))))
     
     
----------------------------------------------------------------------
 
     PROBLEM 3 (25 points)
     
       George (nicknamed the "Big Wave") goes to Las Vegas.  He is
     intrigued by one of the dice games, where n-sided dice (marked with
     numbers from 1 to n on the sides) are being used.  Exactly two dice
     are always thrown, and George wants to build a list of the
     combinations of the values shown on the two dice.
     
       For example, at one table George finds that three-sided dice are
     used, so the possible values are:
     
     (DICE-COMBOS 3) 
     ==> ((1 1) (1 2) (1 3) (2 1) (2 2) (2 3) (3 1) (3 2) (3 3))
     
     Note that both (1 2) and (2 1) appear in the list, as George
     wants to treat these as different combinations.
     
     
     A. George first tries something simple in an attempt to produce the
     above results:
     
     (define (BUGGY-DICE-COMBOS n)
       (let ((vals (enumerate-interval 1 n)))
         (map (lambda (x) (list x n)) vals)))
     
     Write the return value when George evaluates
     
     (BUGGY-DICE-COMBOS 3)
     ==>
     
         ANS: ((1 3) (2 3) (3 3))     
     
     
     B. Write the procedure DICE-COMBOS for George. The pairs of dice
     combinations may appear in any order.  You may also assume you have
     the procedures ENUMERATE-INTERVAL, APPEND, LENGTH, MAP, FILTER,
     and ACCUMULATE as shown on the last page of this quiz handout.
     
     
     
     ANS: Many different ways this can be done.  One simple way is
     shown below (NOTE: this answer is REVISED 10/13/98 compared to
     an earlier version posted in these solutions.)
     
     (define (dice-combos n)
       (let ((vals (enumerate-interval 1 n)))
         (accumulate append nil
            (map (lambda (a) (map (lambda (b) (list a b))
                                  vals))
                 vals))))   

     Note that several solutions are very CLOSE, but depending on the
     way the recursion occurs may fail to generate all the possible
     dice combinations (e.g. may generate (1 3) but not also (3 1)).
     
     



     George wants to use the list of dice combinations to calculate the
     odds that the values of the two dice will sum to any given number, so
     he will know how to place his bets to maximize his winnings (George is
     known for his unrealistic optimism).
     
     For example, in a 3-sided dice game (with the combinations shown
     earlier), the odds of the sum being 4 are:
     
     (FIND-ODDS-OF-SUM 4 3)
     ==> 0.3333 ; 3/9
     
     since 3 combinations (1 3) (2 2) (3 1) out of 9 possible combinations
     sum to 4.
     
     
     
     C. Write the procedure FIND-ODDS-OF-SUM that takes two arguments: the
     SUM and the number of sides N of the dice being used.  Note that you
     may use DICE-COMBOS even if you did not complete part B, as well as
     any of the list procedures on the last page of this quiz handout.
     
     
     ANS:

         (define (find-odds-of-sum sum n)
	   (let ((combos (dice-combos n)))
	     (let ((matches (filter (lambda (combo)
				      (= sum (+ (car combo) (cadr combo))))
				    combos)))
	       (/ (length matches)
		  (length combos)))))
						
     
----------------------------------------------------------------------
     
     PROBLEM 4 (14 points)
     
     After each of the following Scheme expressions, print (or describe
     if unprintable) the value resulting from evaluation of the expression.
     If the expression results in an error, explain why.
     
     A. (lambda (x) (/ y 0))
     
     ANS: A PROCEDURE.  (note that the body never gets evaluated, so
     no error can occur.			 
 
     
     B. ((lambda () 3.14159))
     
     ANS: 3.14159     
     
     
     C. ((lambda (a b) 
           (if (odd? a) 
               (b 2) 
               (+ a b)))
          4 6)
     
     ANS: 10 
     
     
     D. (define f 
          (lambda (m)
            (lambda (n)
              (lambda (p)
                (n m p)))))
        (((f 5) +) (- 7 3))
     
     ANS: 9     
     
     
     
     E. ( (lambda (y) (y 0)) (lambda (x) x) )
     
     ANS: 0     
     
 
     
     F. (let ((x 3))
          (let ((x 7)
                (y (- x 1)))   ; The expression (- x 1) is evaluated OUTSIDE
            (* x y)))          ; the inner let, and so sees the "x=3" binding
     
     ANS: 14. 
     
     
     G. ( (lambda (x y) (+ x y)) 2 3 4 )    
     
    ANS: ERROR - wrong number of arguments (3) to the procedure (expects 2)


----------------------------------------------------------------------
     
 
     PROBLEM 5 (7 points)
     
       Complete the following sentences, which are based on points
     emphasized in the lectures.
     
     
     A. When Rational Math, Inc. wrote code that looked like:
     
     (define (+rat x y)
       (cons (+ (* (car x) (cdr y))
                (* (car y) (cdr x)))
             (* (cdr x) (cdr y))))
     
     they were guilty of ___ABSTRACTION VIOLATION______________________.
     
     
     
     
     
     
     
     B. The three key elements of any programming language (or good
        engineering system) are:
     
        1. _____PRIMITIVES______________________
     
        2. Means of __COMBINATION_______________
     
        3. Means of __ABSTRACTION_______________
     
     
     
     
     
     
     C. The ____CLOSURE_________________ property enables us to nest
     procedure calls arbitrarily deeply by having their return values be of
     the same type as the arguments of those procedures.
     
     
     
----------------------------------------------------------------------
     
     PROBLEM 6 (19 points)
     
       In this problem, we are interested in a tree representation that
     allows us to store values on internal nodes of the tree, as well as
     have any number of children from each node of the tree.  For
     example, we might draw such a tree as:
     
     
                            30
                           /  \
                          /    \
                         5     6
                              /|\
                             / | \
                            /  |  \
                           3   2   1
                              / \
                             /   \
                            1     2
     
     The following data abstraction is used.  A node is assumed to have
     both a VALUE and a list of CHILDREN nodes.  The predicate LEAF?
     returns true if the node has no children (in which case it still has a
     value, but the list of children is the empty list).
     
     (define (make-node value children)
       (list value children))
     
     (define (node-value node)
       (car node))
     
     (define (node-children node)
       (cadr node))
     
     (define (leaf? tree)
       (null? (node-children tree)))
     
     
     
     The tree shown at the top of the page is generated using:
     
     (define big-tree
       (make-node
          30 
          (list (make-node 5 nil)
                (make-node 6 (list (make-node 3 nil)
                                   (make-node 2 (list (make-node 1 nil)
                                                      (make-node 2 nil)))
                                   (make-node 1 nil))))))
     
     
     
     A. The following SMALL-TREE is generated:
     
     (define small-tree
       (make-node 10 (list (make-node 3 nil)
                           (make-node 4 nil))))
     
     Draw a box-and-pointer diagram corresponding to SMALL-TREE.
     
     

     
     
     B. We would sometimes like to see if a tree obeys a particular
     consistency requirement.  In particular, we would like to check if the
     value of a node is equal to some operation on the values of the
     children of that node.  For example, we might want a node value to be
     equal to the product of the values of its children.  In the case of
     BIG-TREE, it does satisfy this condition, while SMALL-TREE does not:
     
     (check-tree * 1 big-tree) ==> #t
     (check-tree * 1 small-tree) ==> #f
     
     The following procedure is intended to perform this check.  You are to
     complete the procedure by providing the missing expressions.
     
     (define (check-tree op init tree)
       (define (check-subtrees children)  ; children should be a LIST of nodes
         (if (null? children)
             #t
             (and (check-tree op init ( children))   ; first child
                  (check-subtrees ( children)))))    ; rest of children
       (if (leaf? tree)
           #t
           (and (= ( tree)
                   (accumulate op init (map node-value (node-children tree))))
                (check-subtrees (node-children tree)))))
     
      = ANS: CAR
     
     
      = ANS: CDR
     
     
      = ANS: NODE-VALUE
     
 
     PROBLEM 6, Continued
     
     C. We next want a procedure that aggregates leaf information into node
     information in a new tree.  For example, we might like to copy the
     BIG-TREE above, but instead of the node values being equivalent to the
     product of the values of the children, we might want the node values
     to be equal to the sum of the values of the children (throughout the
     entire tree).  If a node is a leaf node, we just copy the node value
     for that leaf.
     
     For example, we would like (TRANSFORM-TREE + 0 TEST-TREE) to produce
     a new tree that looks like:

**
NOTE BUG: TEST-TREE above should be SMALL-TREE     
**

                            12   (where the top node value 12 = 5+7)
                           /  \
                          /    \
                         5     7   (where the right node value 7 = 3+3+1)
                              /|\
                             / | \
                            /  |  \
                           3   3   1    (where the middle node value 3 = 1+2)
                              / \
                             /   \
                            1     2
     
     
     Complete the definition of the TRANSFORM-TREE procedure,
     which looks very similar to the CHECK-TREE procedure with 
     only small changes.  (The  and  you previously
     wrote should still work here.)  
     
     (define (transform-tree op init tree)
       (define (transform-subtrees children)
         (if (null? children)
             nil
             ( (transform-tree op init ( children))
                     (transform-subtrees ( children)))))
       (if (leaf? tree)
           
           (make-node (accumulate op init (map node-value 
                                               (node-children tree)))
                      (transform-subtrees (node-children tree)))))
     
** NOTE BUG: The (if ...) above should be
 
  (let ((new-subtrees (transform-subtrees (node-chilren tree))))
    (if (leaf? tree)
        
        (make-node (accumulate op init (map node-value new-subtrees))
                   new-subtrees)))

**

      = ANS: CONS
     
     
      = ANS: TREE

----------------------------------------------------------------------

                                LIST HANDLING PROCEDURES
     
     Definitions are provided here for your convenience.
     
     
     (define (append s1 s2)
       (if (null? s1)
           s2
           (cons (car s1)
                 (append (cdr s1) s2))))
     
     
     (define (length lst)
       (if (null? lst) 0 (+ 1 (length (cdr lst)))))
     
     
     (define (map op lst)
       (if (null? lst)
           nil
           (cons (op (car lst))
                 (map op (cdr lst)))))
     
     
     (define (filter pred lst)
       (cond ((null? lst) nil)
             ((pred (car lst))
              (cons (car lst) (filter pred (cdr lst))))
             (else (filter pred (cdr lst)))))
     
     
     (define (accumulate op init lst)
       (if (null? lst)
           init
           (op (car lst)
               (accumulate op init (cdr lst)))))