Functional Problem Solving (CSC 151 2015F) : EBoards

CSC151 2015F, Review Session Week 14 - 2015-12-10


Overview

Admin

About the Exam

We discussed the exam in class yesterday. It's comprehensive. It will have four questions. It will be somewhere between quiz questions and exam questions.

We may cover every topic. We will almost certainly cover something related to sorting.

Can we ask you questions about confusingly worded problems? Yes. However, I will mostly be there for clarification, not guidance.

Sample Final Questions

We will not get to all of these. There are also three others on the sample final examination.

There are enough questions here that I would recommend that you look at them online for a few minutes and then discuss which you would like to do first.

Votes:

Using Sorting Routines

Assume that we represent names as lists of the form (last-name first-name). Write an expression to merge the following two lists:

(define mathstats-faculty
  (list (list "Blanchard" "Jeff")
        (list "Chamberland" "Marc")
        (list "Fellers" "Pamela")
        (list "French" "Chris")
        (list "Jonkman" "Jeff")
        (list "Kuiper" "Shonda")
        (list "Mileti" "Joseph")
        (list "Moore" "Emily")
        (list "Moore" "Tom")
        (list "Olsen" "Chris")
        (list "Paulhus" "Jennifer")
        (list "Shuman" "Karen")
        (list "Wolf" "Royce")))

(define more-faculty
  (list (list "Moore" "Chuck")
        (list "Moore" "Ed")
        (list "Moore" "Gordon")
        (list "Moore" "Roger")))

A Solution

We need a comparator that takes two names and determines whether one can come before the other. A name is a list of length 2.

(define name-may-precede?
   (lambda (name1 name2)
     (let ([last1 (car name1)]
           [first1 (cadr name1)]
           [last2 (car name2)]
           [first2 (cadr name2)])
       (cond
         [(string-ci<? last1 last2)
          #t]
         [(string-ci>? last1 last2)
          #f]
         [(and (string-ci=? last1 last2)
               (string-ci<=? first1 first2))
          #t]
         [else
          #f]))))

(define name-may-precede?
   (lambda (name1 name2)
     (let ([last1 (car name1)]
           [first1 (cadr name1)]
           [last2 (car name2)]
           [first2 (cadr name2)])
       (string-ci<=? (string-append last1 ", " first1)
                     (string-append last2 ", " first2)))))

Modes of Image Making

We have learned four primary mechanisms for making images: drawings as values, image-compute, GIMP tools, and turtles. Using each of these four mechanisms, draw the outline of a black circle of radius 40, centered at (50,50), on a white background.

A Solution, using image-compute

(image-show (image-compute (lambda (col row)
                             (let ([distance-from-center
                                    (sqrt (+ (square (- 50 col))
                                             (square (- 50 row))))])
                               (if (< 38 distance-from-center 42)
                                   (irgb 0 0 0)
                                   (irgb 255 255 255))))
                           100 100))

A solution using GIMP tools

(context-set-bgcolor! "white")
(context-set-fgcolor! "black")
(define canvas (image-show (image-new 100 100)))
(image-select-ellipse! canvas REPLACE 10 10 80 80)
(context-set-brush! "2. Hardness 100" 2)
(image-stroke! canvas)

Turtle-gone

Write a procedure, (turtle-gon turtle sides side-length) that uses a turtle to draw a regular polygon of the specified number of sides and side length.

Reversing Vectors

Write a procedure, (vector-reverse! vec), that reverses a vector "in place". For example,

> (define vec1 (vector 1 2 3 'a 'b 'c))
> vec1
'#(1 2 3 a b c)
> (vector-reverse! vec1)
> vec1
'#(c b a 3 2 1)
> (vector-reverse! vec1)
> vec1
'#(1 2 3 a b c)

Whatzitdo

Consider the following procedure.

(define whatzitdo
  (lambda (lst)
    (let where ([here 0]
                [there (- (vector-length lst) 1)])
      (if (> there here)
          empty
          (let ([elsewhere (quotient (+ here there) 2)])
            (node (vector-ref lst elsewhere)
                  (where here (- elsewhere 1))
                  (where (+ elsewhere 1) there)))))))

a. Describe or show the result of calling whatzitdo on the collection of values 5 2 3 1 8 9 3 2 12.

b. Rewrite whatzitdo so that the various names (e.g., whatzitdo, lst, here) are clearer.

c. Write the six-P style documentation for whatzitdo.

What's Wrong?

The following procedure is poorly designed. Explain why, and suggest three different ways of fixing the problem.

(define list-largest
  (lambda (lst)
    (cond
      [(null? (cdr lst))
       (car lst)]
      [(> (car lst) (list-largest (cdr lst)))
       (car lst)]
      [else
       (list-largest (cdr lst))])))

What's Wrong?

The following procedure to count the number of integers in a file. What is wrong with this procedures? Rewrite it so that it is likely to work correctly.

(define tally-integers
  (lambda (file-name)
    (let kernel ([port (open-input-file file-name)])
      (let ([next-val (read port)])
        (cond
          [(eof-object? (read port))
           (close-output-port file-name)
           0]
          [(integer? (read port))
           (+ 1 (tally-integers file-name))]
          [else
           (tally-integers port)])))))

A Solution

Here's a version that tells us how it's thinking.

(define file-tally-integers
  (lambda (file-name)
    (let kernel ([port (open-input-file file-name)])
      (let ([next-val (read port)])
        (display "I read ") 
        (display next-val)
        (cond
          [(eof-object? next-val)
           (display " and hit the end of the file")
           (newline)
           (close-input-port port)
           0]
          [(integer? next-val)
           (display " and it's an integer")
           (newline)
           (+ 1 (kernel port))]
          [else
           (display " and I'm ignoring it")
           (newline)
           (kernel port)])))))

More Code Reading

Consider the following two definitions:

(define stuff1
  (append (list 1)
          (append (list 2)
                  (append (list 3)
                          (append (list 4)
                                  (append (list 5)
                                          null))))))
(define stuff2
  (append (append (append (append (append (list 1) 
                                          (list 2))
                                  (list 3))
                          (list 4))
                  (list 5))
          null))

a. What do stuff1 and stuff2 look like?

> stuff1


> stuff2

b. How many calls to cons are made by append and list in creating stuff1?

append:

list:

c. How many calls to cons are made by append and list in creating stuff2?

append:

list:

Problem 3 from the Sample Exam

A Solution

If I start with the list '(1 2 3 4), list-reverse-1 says "append the reverse of '(2 3 4) to (1)" Append will spend 3 calls to cons doing that

To build the reverse of '(2 3 4), we must append the reverse of '(3 4) to (2). That requires 2 calls to cons.

To build the reverse of '(3 4), we must append the reverse of (4) to (3). That requires 1 call to cons.

6 calls to cons for list-reverse-1 of a list of length 4.

7+6+5+4+3+2+1 = 28 calls to cons for list-reverse-1 of a list of length 8?

If we are counting calls to car, we have one call to car for every call to cdr in append. We also have one call to car in list-reverse-1 for each element in the list.

So ... for four elements, we have 6 + 4 = 10 calls to car.

For eight elements, we have 28 + 8 = 36 calls to car.

Additional Topics

Files