Functional Problem Solving (CSC 151 2015F) : EBoards
Primary: [Front Door] [Schedule] - [Academic Honesty] [Disabilities] [Email] - [FAQ] [Teaching & Learning] [Grading] [Taking Notes] [Rubric] [Remote Access]
Current: [Assignment] [EBoard] [Lab] [Outline] [Reading]
Sections: [Assignments] [EBoards] [Labs] [Outlines] [Readings] - [Examples] [Handouts]
Reference: [Setup] [VM] [Errors] - [Functions A-Z] [Functions By Topic] - [Racket] [Scheme Report (R5RS)] [R6RS] [TSPL4]
Related Courses: [Curtsinger (2015F)] [Davis (2013F)] [Rebelsky (2015S)] [Weinman (2014F)]
Misc: [Submit Questions] - [SamR] [Glimmer Labs] [CS@Grinnell] [Grinnell] - [Issue Tracker (Course)]
Overview
Admin
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.
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:
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")))
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)))))
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.
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))
(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)
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.
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)
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.
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))])))
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)])))))
kernel?next-val.
read-val multiple times is dangerous. It means that we
may be reading multiple values. E.g., we could read 3 and call it
next-val, then read another value and see that it's the end of file.
We will not count that 3.port is an input port, so we should use close-input-portport, not file-name for the call to close.Rather than recursing on file-tally-integers, we should recurse on kernel.
(define file-tally-integers (lambda (file-name) (let kernel ([port (open-input-file file-name)]) (let ([next-val (read port)]) (cond [(eof-object? next-val) (close-input-port port) 0] [(integer? next-val) (+ 1 (kernel port))] [else (kernel port)])))))
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)])))))
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:
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.
(open-input-file FILENAME) creates the port for a file. It has
a location and a file.(let ([black (open-input-file "stuff.txt")] [green (open-input-file "stuff.txt"))), both black and green refer to the same file, but may be at different locations in the file during our computation.(close-input-port PORT) or (close-output-port PORT).