CS 37

Clab 6: Slow growth, rapid growth, Divide and Conquer; Functions as first-class objects, more with lists


I'll say a few words about logarithms and especially logs to base 2 and and the G-rated version of Ackermann's function.

Since I don't have superscripts and subscripts on these pages, I will use log n to represent log to the base 2 of n and x^y to represent x raised to the y power.
Recall that log n = k if 2^k = n. So log 16 = 4, log 32 = 5,
log 128 = 7, log 1024 = 10.
Keep in mind that:
100^3 = 1,000,000
log 1,000,000 is about 20
2^100 >> the number of microseconds since the big bang.
This means that if your algorithm has a running time of O(2^n) on inputs of size n, and if you want to use it on an input of size 100, you will have to wait a looooong time to get an answer even if your computer performs a million steps a second. O(n^3) algorithms don't take too long on 100 inputs and O(log n) algorithms are fast on 1,000,000 inputs.

Here is the G-rated version of Ackermann's function.

;;EXERCISE 1.10 (define (A x y) (cond ((= y 0) 0) ((= x 0) (* 2 y)) ((= y 1) 2) (else (A (- x 1) (A x (- y 1)))))) If you define f(x) to be A(x,x), f is a computable function that is extremely rapidly growing. The sun will become a red giant and swallow the earth before our fastest computers can finish computing f(4).

Review the material in text on pp. 62-65 on lambda and let http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-12.html#%_sec_1.3.2 . From r5rs in on-line help in drscheme, read about lambda and let (the binding construct meaning -- shun the sinful iteration material) Make sure you understand the examples illustrated and how the values were obtained. Ask questions if you have them.

Now enter the search procedure given on page 67.

(define (search f neg-point pos-point) (let ((midpoint (average neg-point pos-point))) (if (close-enough? neg-point pos-point) midpoint (let ((test-value (f midpoint))) (cond ((positive? test-value) (search f neg-point midpoint)) ((negative? test-value) (search f midpoint pos-point)) (else midpoint)))))) (define (close-enough? x y) (< (abs (- x y)) 0.001)) (define average (lambda (x y) (/ (+ x y) 2))) (define cube (lambda (x) (* x x x))) Make sure you understand what it is doing. You will need to define average and close-enough? if you have not done so already. The function cube that we have used before has a root at 0. Test search by evaluating: (search cube -1 2.0). This is an example of a divide and conquer algorithm. Divide and conquer is a general algorithm design technique. Using this technique, one tries to find a way to divide a problem in half (approximately) and then solve just half a problem (or even two halves sometimes, hoping that solving two halves will be easier than solving one whole). Turn trace on search and average and evaluate (search cube -1 2.0) again. Make sure you see how the algorithm is dividing the region where the root may be in half each pass through. The number of thousandths (.001s) between -1 and 2 is 3000 so you can se that the complexity of this algorithm is logarithmic in the size of the interval divided by the accuracy desired.

x^2-4 is a function with root at 2. Without naming this function, we can express it as (lambda (x) (- (square x) 4)). Try search on this function by evaluating: (search (lambda (x) (- (square x) 4)) 0 3.0). Check that you got the root.

1-x is the equation of the straight line that passes through the the points (0, 1) and (3, -2). We can express it as (lambda (x) (- 1 x)). Find the root of 1 -x by evaluating: (search (lambda (x) (- 1 x)) 0 3.0). You should have gotten an answer. BUT--Don't bet your life on the answer you got. What is the right answer? Did you get the right answer? Why not? What do you have to do to get the right answer? Now read page 67 again and then page 68.

Now carefully review the material on pages 73-75. http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-12.html#%_sec_1.3.4

Define deriv as in the text . Note that deriv is a procedure that takes one argument, a function, and returns a function that is an approximation to the derivative of the first argument. deriv expects to be executed in an environment where dx is defined to be a small positive real number (e.g. 0.00001). You should have the functions square and cube defined from before. If not, define them now. Define dx to be 0.001. Now evaluate

(define Dsquare (deriv square)) Dsquare is a function that is an approximation to the derivative of x^2. That is Dsquare is a function that should be very close to the function 2x. Try evaluating Dsquare on some values and check that it does behave like an approximation to the function 2x. Now evaluate (define g (deriv cube)) g should be an approximation to the function 3x^2 which is the derivative of x^3. Check it on a few values.

The composition of 2 functions f and g, sometimes written fg is defined by fg(x) = f(g(x)). That is first apply g to x, then apply f to the result. For example if f(x) = x^3 and g(x) = 1 + x, then fg(x) = (1 + x)^3. We want to define a procedure that takes two functions as arguments and returns the composition of those two argument functions. Here is a start:

;;;given the 2 functions f and g, compose returns the composition fg (define (compose f g) (...you fill in this part) ;;; for convenience we will define the function 1+ which increments ;;; its argument by one. (define 1+ (lambda (x) (+ 1 x))) For example: > (1+ 7) 8 After you have successfully defined compose, you should be able to evaluate: (define h (compose cube 1+)) If you did it right h should be the function h(x) = (1 + x)^3.

Try it and check h for a few values. Try some other compositions.

Ask any questions you may have.


Now, define and debug the following functions.
Ask questions if you have them.
Make sure your language level is Full Scheme.

;; count returns the number of times the atom sym occurs in the ;; list l: (define count (lambda (sym l) ..... ;; rev returns the reverse of the list lst (define rev (lambda (lst) ... For example: > olymp (skating skiing slalom bobsled) > (rev olymp) (bobsled slalom skiing skating)