Fundamentals of CS I (CS151 2001S)

[Current]
[Discussions]
[Glance]
[Honesty]
[Instructions]
[Links]
[News]
[Search]
[Syllabus]
**Primary**

[Examples]
[Exams]
[Handouts]
[Homework]
[Labs]
[Outlines]
[Quizzes]
[Readings]
[Reference]
**Sets**

[Blackboard]
[Scheme Report]
[SamR's Schedule]
[Rebelsky/Fall 2000]
[Walker/Fall2000]
[Stone/Spring2000]
**Links**

**Distributed:** Friday, 6 April 2001

**Due:** 9 a.m., Monday, 16 April 2001

*Those with extenuating circumstances may request an
extension on the exam. Such requests must be received by
9 a.m. Thursday, 12 April 2001.*

This page may be found online at
`http://www.cs.grinnell.edu/~rebelsky/Courses/CS151/2001S/Exams/exam.02.html`

.

There are three problems on the exam. Each problem is worth the same number of points. Some problems may be broken up into subproblems. The point value associated with a problem does not necessarily correspond to the complexity of the problem or the time required to solve the problem.

This examination is open book, open notes, open mind, open computer, open Web. However, it is closed person. That means you should not talk to other people about the exam. Other than that limitation, you should feel free to use all reasonable resources available to you. As always, you are expected to turn in your own work. If you find ideas in a book or on the Web, be sure to cite them appropriately.

This is a take-home examination. You may use any time or times you deem appropriate to complete the exam, provided you return it to me by the due date. It is likely to take you about five to ten hours, depending on how well you've learned topics and how fast your work. I would appreciate it if you would write down the amount of time each problem takes. I expect that someone who has mastered the material and works at a moderate rate should have little trouble completing the exam in a reasonable amount of time. Since I worry about the amount of time my exams take, I will give three points of extra credit to the first two people who honestly report that they've spent at least eight hours on the exam. (At that point, I may then change the exam.)

Over the past few weeks, I've designated a few talks (some CS talks;
some convocation talks) as *extra credit*. Please indicate
which, if any, of those talks you've attended.

You must include both of the following statements on the cover sheet of the examination. Please sign and date each statement. Note that the statements must be true; if you are unable to sign either statement, please talk to me at your earliest convenience. Note also that ``inappropriate assistance'' is assistance from (or to) anyone other than myself or our teaching assistant.

1. I have neither received nor given inappropriate assistance on this examination.

2. I am unaware of any other students who have given or received inappropriate assistance on this examination.

Because different students may be taking the exam at different times, you are not permitted to discuss the exam with anyone until after I have returned it. If you must say something about the exam, you are allowed to say ``This is among the hardest exams I have ever taken. If you don't start it early, you will have no chance of finishing the exam.'' You may also summarize these policies. You may not tell other students which problems you've finished.

Answer all of your questions electronically and turn them in in hardcopy. That is, you must write all of your answers on the computer and print them out. You should also email me a copy of your exam by copying your exam and pasting it into an emal message. Put your answers in the same order that the problems appear in. Make sure that your solution confirms to the format for laboratory writeups

In many problems, I ask you to write code. Unless I specify otherwise in a problem, should write working code and include examples that show that you've tested the code.

You should fully document all of the primary procedures (including parameters, purpose, value produces, preconditions, and postconditions). If you write helper procedures (and you may certainly write helper procedures) you should document those, too, although you may opt to write less documentation. When appropriate, you should also include short comments within your code. You should also take care to format your code carefully.

Just as you should be careful and precise when you write code, so should you be careful and precise when you write prose. Please check your spelling and grammar.

I will give partial credit for partially correct answers. You ensure
the best possible grade for yourself by emphasizing your answer and
including a *clear* set of work that you used to derive the
answer.

I may not be available at the time you take the exam. If you feel that a question is badly worded or impossible to answer, note the problem you have observed and attempt to reword the question in such a way that it is answerable. If it's a reasonable hour (before 10 p.m. and after 8 a.m.), feel free to try to call me in the office (269-4410) or at home (236-7445).

I will also reserve time at the start of classes next week to discuss any general questions you have on the exam.

One of the tasks faculty frequently encounter is the assignment of a letter grade based on the numeric grades that students have received over the course of a semester. Grading rubrics differ greatly. Some faculty simply average grades; others sum grades; others give different aspects different weights.

Suppose we've decided to store all the grades for a class in a file. One mechanism would be to have one list for each student in the class. The list will have the form

(last-name first-name email grade_{1}grade_{2}... grade_{n})

For example, here is the list of grades for a fictitous class in which
students have received four grades. You can find the list in the
file `samplegrades`

.

("Aardvark" "Arnie" "aa@grinnell.edu" 100 50 80 90) ("Beetle" "Betty" "bb@grinnell.edu" 85 85 90 85) ("Chihuahua" "Chuck" "cc@grinnell.edu" 90 90 90 0) ("Dingo" "Donna" "dd@grinnell.edu" 95 95 95 80) ("Elephant" "Ernie" "ee@grinnell.edu" 5 0 0 0) ("Fox" "Fiona" "ff@grinnell.edu" 80 80 80 100)

How will we process the list of grades? By reading each entry from the file, calling an appropriate grading procedure, and doing something with the result. For example, we might write the results to a file.

The procedure we write for processing grades needs at least two parameters: the name of the input file and the name of the output file. Are there others? To make our procedure as general as possible, we can also make the grading procedure a parameter. For example, if a faculty member's rubric is ``average the grades'', the procedure can be

(lambda (grades) (divide (sum grades) (length grades)))

Similarly, if a faculty member's rubric is ``average the grades after dropping the lowest'', the procedure can be

(lambda (grades) (divide (- (sum grades) (min grades)) (- (length grades) 1))

For the more complex ``best two of three exams count 50%; final counts 50%'', we might write

(lambda (grades) (let* ((sedarg (reverse grades)) (final (car sedarg)) (exams (cdr sedarg))) (+ (divide final 2) (divide (- (sum exams) (min exams)) 4))))

Note that for computing grades, we don't care about the name or email; we care only about the numbers.

**Problem:**
Document, write, and test a procedure,
`(process-grades `

,
that reads a sequence of grade entries from *infile* *outfile* *gradeproc*)*infile*, processes each entry
with *gradeproc*, and writes a *neatly-formatted* grade report to
*outfile*. For example, for the example above with the rubric of
``use the best grade'', the output file might contain

LAST NAME FIRST NAME GRADE --------- ---------- ----- Aardvark Arnie 100 Beetle Betty 90 Chihuahua Chuck 90 Dingo Donnna 95 Elephant Ernie 5 Fox Fiona 100

In grading this problem, I will look at how well you process the input file, how well you generate the output file, how you deal with procedures as parameters, and how you format the output. If you can't do everything right, you should attempt to show your ability to do some aspects by simplifying some parts of the problem (e.g., by reading grades from a list rather than a file, by generating a list rather than a file, by hardcoding the grading procedure, or by ignoring formatting in the output file).

You should be quite familiar with the `map`

procedure.
In its standard form, `map`

takes two parameters,
*proc*, a procedure of one argument, and *values*, a
list of values. The `map`

procedure builds a new list
by applying *proc* to each element of *values*.

As you may recall from our discussion, Scheme provides vectors as an alternative to lists. Vectors differ from lists in a few key ways: vectors have a fixed size, vectors provide indexed access, and vectors are mutable.

It therefore makes sense to design a variant of `map`

for
vectors. Rather than building a new vector, we'll have the variant
change the elements *in place*. Hence, we call the modified
version `map!`

. Here are some examples of the
desired use.

>(define grades (vector 80 66 92 50 23))>grades#(80 66 92 50 23) >(map! (lambda (val) (* 2 val)) grades)>grades#(160 132 184 100 46) >(map! (right-section - 40) grades)>grades#(120 92 144 60 6)

Document, write, and test `map!`

. Note that I will look
for tests that go beyond my simple examples.

You may have noted that we permit procedures to have zero, one, two, or more
parameters. Some time ago, a Mathematician named Haskell B. Curry suggested
that all procedures be designed to take exactly one parameter. Is that possible?
Certainly. One technique would be to have procedures take a list as a parameter.
However, it is also possible to simulate procedures of multiple arguments by having
the single-argument procedures return other single argument procedures. We
call this process *currying*.

In general, instead of defining a procedure of *n* parameters as

(defineproc(lambda (param1param2...paramn)body))

we use

(defineproc(lambda (param1) (lambda (param2) ... (lambda (paramn)body) ...)))

Similarly, instead of calling that procedure with

(procarg1arg2...argn)

we use

((...((procarg1)arg2) ...)argn)

For example, here is a curried version of `max`

(define cmax (lambda (a) (lambda (b) (if (> a b) a b))))

We would use it as follows:

>((cmax 5) 6)6 >((cmax 2) 1)2

Similarly, here are curried versions of `add`

and `expt`

.

;;; Procedure: ;;; cadd ;;; Parameters (curried): ;;; a, a number ;;; b, a number ;;; Purpose: ;;; Adds a and b. ;;; Produces: ;;; sum, a number ;;; Preconditions: ;;; a and b are numbers. ;;; a+b is computable. ;;; Postconditions: ;;; sum = a+b (define cadd (lambda (a) (lambda (b) (+ a b)))) ;;; Procedure: ;;; cexpt ;;; Parameters (Curried): ;;; base, a number ;;; power, a natural numbers ;;; Purpose: ;;; Multiplies power copies of base. ;;; Produces: ;;; result, a number ;;; Preconditions: ;;; base and power are numbers. ;;; power is a non-negative integer ;;; The result is computable. ;;; Postconditions: ;;; result = base * base * ... * base, where there are ;;; power copies of base. (define cexpt (lambda (base) (lambda (power) (expt base power))))

We can even write a curried version of `map`

;;; Procedure: ;;; cmap ;;; Parameters (Curried): ;;; proc, a procedure ;;; lst, a list ;;; Purpose: ;;; Applies proc to each element of lst. ;;; Produces: ;;; newlst, a list. ;;; Preconditions: ;;; proc takes one parameter ;;; proc can be legally applied to each element of lst. ;;; Postconditions: ;;; newlst is of the same length of lst ;;; Each element, n, of newlst, is the result of applying ;;; proc to the corresponding element of lst. (define cmap (lambda (proc) (lambda (lst) (if (null? lst) null (cons (proc (car lst)) ((cmap proc) (cdr lst)))))))

What are the advantages of currying? For the implementer, it is often easier to design a system in which all procedures have only one parameter. However, there are also advantages for the programmer. In particular, it's very easy to form the left section of any curried procedure. All you do is give it the first parameter!

For example, the procedure that adds two to any argument can be written
as `(cadd 2)`

(rather than the more cumbersone
`(left-section + 2)`

. Similarly, the procedure
that adds two to all members of a list can be written
`(cmap (cadd 2))`

.

a. Using `cmap`

and `cexpt`

, compute the list
of the first eleven powers of 2 (that is, 1, 2, 4, 8, 16, ..., 512, 1024).

b. Document, write, and test `csub`

and
`cmult`

, curried procedures of two parameters that
respectively subtract and multiply their parameters.

c. Document, write, and test `cmember?`

, a curried procedure
of two parameters that checks whether the first parameter (a value) is a
member of the second parameter (a list).

d. Document, write, and test `c-right-section`

, a curried
version of right section that expects a curried two-parameter procedure
as its first parameter and a value as a second parameter. Your
procedure should then fill in the second parameter of the two-parameter
procedure.

**The following note was added on 10 April 2001**

For example, given the `cexpt`

defined above,
you might write

(define square ((c-right-section cexpt) 2))

When you applied `square`

to 3, you would get 9.

e. One of the most commonly used higher-order procedures is `compose`

.
Compose takes two single-parameter procedures as parameters and creates a
procedure that applies the second and then the first. For example, if we
wanted a procedure to multiply a number by 5 and then add 2, we might write

(compose (cadd 2) (cmult 5))

or, in curried form

((ccompose (cadd 2)) (cmult 5))

For example,

>(define scale (compose (cadd 2) (cmult 5)))>(scale 3)17 >(scale 1/5)3

Document, write, and test `ccompose`

.

Wednesday, 4 April 2001

- Created.
- Sketched problems 1 and 3; wrote problem 2.
- Copied guidelines from a previous exam.

Thursday, 5 April 2001

- Filled in problems 1 and 3.
- Updated guidelines.

Friday, 6 April 2001

- Released.

Wednesday, 11 April 2001

- Added a note on
`c-right-section`

. - Changed an incorrect result from
`((cmax 2) 1)`

- This version available at
`http://www.cs.grinnell.edu/~rebelsky/Courses/CS151/2001S/Exams/exam.02.html`

.

[Current]
[Discussions]
[Glance]
[Honesty]
[Instructions]
[Links]
[News]
[Search]
[Syllabus]
**Primary**

[Examples]
[Exams]
[Handouts]
[Homework]
[Labs]
[Outlines]
[Quizzes]
[Readings]
[Reference]
**Sets**

[Blackboard]
[Scheme Report]
[SamR's Schedule]
[Rebelsky/Fall 2000]
[Walker/Fall2000]
[Stone/Spring2000]
**Links**

**Disclaimer**:
I usually create these pages on the fly. This means that they
are rarely proofread and may contain bad grammar and incorrect details.
It also means that I may update them regularly (see the history for
more details). Feel free to contact me with any suggestions for changes.

This page was generated by Siteweaver on Thu May 3 23:10:03 2001.

This page may be found at `http://www.cs.grinnell.edu/~rebelsky/Courses/CS151/2001S/exam.02.html`

.

You may validate
this page's HTML.

The source was last modified Mon Apr 16 08:48:12 2001.