University of Virginia, Department of Computer Science
CS200: Computer Science, Spring 2003

Exam 1 - Comments

Cost of Nothing, Value of Everything

For each of these questions, explain what the given Scheme expression evaluates to or what error would be produced when it is evaluated.

You do not need to show all the evaluation steps, but the more clearly you show how the expression is evaluated, the more likely you are to receive some credit even if your answer is incorrect. If you think there would be an error, make sure to be especially clear about which evaluation or application rule produces the error.

Remember you may not use a Scheme interpreter during this exam!

1. (< 5 4)

2. (if (< 5 4) (+ + +) 12)
Follow the evaluation rule for if carefully — if the test evaluates to false, the consequent expression is never evaluated so it does not matter that evaluating (+ + +) would produce an error.
3. ((lambda (a b) (+ a b)) 3)
Error — the expression is an application where the procedure to apply takes two parameters, but the application expression only has one parameter.
  (map (lambda (x) (* x 2)) 
       (cons 50 (cons 100 (cons 200 null))))))
200 (of course!)

The Root of All Evil...

Enron's accountants have requested a procedure that takes a list of numbers, and evaluates to the list with all the negative numbers removed. For example, (enronize (list 5 -17 4000 13 0 -23 12)) should evaluate to the list (5 4000 13 0 12).

5. Define the enronize procedure. For this question you should not use insertl (or anything similar) in your definition.

(define (enronize lst)
  (if (null? lst) null
      (if (>= (car lst) 0)
	  (cons (car lst) (enronize (cdr lst)))
	  (enronize (cdr lst)))))

6. Define the enronize procedure using insertl. For this question, you must use insertl (as defined on Notes 8) to do most of the work.
(define (enronize lst)
  (insertl lst
	   (lambda (first rest)
	     (if (>= first 0)
		 (cons first rest)
7. How much work is the enronize procedure you defined in question 5? Express your answer using Θ notation, and include a brief explanation why it is correct. If you use n in your answer, be sure to explain what it means.
Both our enronize procedures are Θ(n) where n is the length of the list parameter. If the length of the list doubles, we need to do twice as much work since for every element on the list the most work we do is one car, one >= comparison, one cons and then we evaluate (enronize (cdr lst)). The primitive procedures car, cdr, >= and cons are all Θ(1) since the work they do does not depend on the length of the list. We will call enronize n times since each time the list parameter will be (cdr lst) which is one shorter than the length of the previous list parameter. Hence, the total work is Θ(n).
The SEC has caught on to Enron's accounting scheme, and Enron's new chief accountant has requested a more general version of the enronize procedure. Instead of always eliminating all negative values, it should be able to eliminate all values below a given value. To be able to produce all possible enronize procedures, define a make-enronize procedure that takes one parameter lowval, evaluates to a procedure that eliminates all values below lowval from the input list. For example, (make-enronize 0) should evaluate to the original enronize procedure that eliminates all the negative values, and
   ((make-enronize -2) (list 5 -7 -2 12 -23))
should evaluate to the list (5 -2 12).

8. Define the make-enronize procedure. You may use insertl if you want, but are not required to.

This was a tricky one, since you need to define make-enronize so applying it will produce a procedure. Hence, the body of make-enronize will need to use lambda to make a procedure. Here's the easiest way:
(define (make-enronize lowval)
  (lambda (lst)
    (insertl lst
	     (lambda (first rest)
	       (if (>= first lowval)
		   (cons first rest)
Note that the body of the lambda is the same as our answer to question 6, except with 0 replaced by lowval.

Another way is to try to use the question 5 answer, but this is trickier. We can't just call enronize in the body of make-enronize, since that will call the original enronize procedure that just removed the negative values. So, we need to use (make-enronize lowval) in place of enronize in the new procedure.

(define (make-enronize lowval)
  (lambda (lst)
    (if (null? lst) null
	(if (>= (car lst) 0)
	    (cons (car lst) ((make-enronize lowval) (cdr lst)))
	    ((make-enronize lowval) (cdr lst))))))
A third approach is to subtract lowval from every element in the list, then use the original enronize procedure, and then add lowval to every element in the list:
(define (make-enronize lowval)
  (lambda (lst)
    (map (lambda (el) (+ el lowval))
	 (enronize (map (lambda (el) (- el lowval)) lst)))))

...Doesn't Grow on Trees

In Lecture 13 we used binary trees to sort quickly. For this problem, you will define a procedure that takes a binary tree as input, and evaluates to its mirror image: the tree we would see if we held up a mirror to the right side of the input tree. For example, if the input is the tree on the left, the output should be the tree on the right:

               5          |           5
              / \         |          / \
             /   \        |         /   \
            2     8       |        8     2 
           / \   /        |         \   / \
          1   4  7        |          7 4   1
           input        mirror      output
Note that the null children are not shown. Observe that the mirror image tree is produced by swapping the left and right sides at every node.

9. Define the mirror-tree procedure that takes a tree as input, and evaluates to its mirror image tree. You may use the tree procedures we defined in Lecture 13: make-tree, get-left, get-element and get-right. If you are not sure your code is completely correct, you should explain in clear English what you are doing.

The mirror of a null tree is null. To mirror any other tree, we just make a new tree where the left tree is the mirror of the input tree's right tree, and the right tree is the mirror of the input tree's left tree:
(define (mirror-tree tree)
  (if (null? tree) null
      (make-tree (mirror-tree (get-right tree))
		 (get-element tree)
		 (mirror-tree (get-left tree)))))
10. How much work is your mirror-tree procedure? Express your answer using Θ notation, where n is the number of nodes in the input tree. Include a brief explanation why it is correct. Also, explain why it is not possible for someone else to write a correct mirror-tree procedure that is significantly less work.
Θ(n). The easy way to see this is to notice that mirror tree must swap the branches of every node in the tree. To swap branches of a node requires constant work — it doesn't matter how big the subtrees are, the work required to make-tree is always the same since it just puts three items into a list. There is no way to do better than this, since we must visit every node in the tree, otherwise we cannot produce a correct mirror image.
11. (Optional, no credit) Do you feel your performance on this exam will fairly reflect your understanding of the course material so far? If not, explain why.
Most people seemed to think it was fair, except for placing too much emphasis (20% of the exam) on measuring work. Its true that we have not covered this enough for you to be expected to completely understand it, and in particular we haven't yet seen a clear explanation of what Θ notation really means. We will cover this a bit later in the course.

I few commented that it seemed easier than last year's exam. I don't think this is true, its just that by studying last year's exam you learned what you needed for this exam. Last year's exam only had one question (defining reverse) from the PhD qualifiers on it, and yours had five (essentially everything except the evaluate these expressions part and question 8 which my colleagues considered too difficult for our PhD students). On the other hand, last year's students got wisdom points and you didn't deserve them since you had the benefit of last year's students to convince you to take the class and to conduct lab hours and review sessions. I hope next year's students will get so much benefit from knowing both this year's and last year's students, that they will deserve some anti-wisdom points!

CS 200

CS 200: Computer Science
Department of Computer Science
University of Virginia

Circle Fractal by Ramsey Arnaoot and Qi Wang
Using these Materials