Exam 1

Assigned: Wednesday, September 14

Due: Tuesday, September 20 by 10:30pm

Please read the exam procedures page for policies, turn-in procedures, and grading details. If you have any questions about the exam, check the Q&A at the bottom of this page. We will generally spend some time in class every day on questions and answers while the exam is in progress.

While the exam is out, please check back periodically to see if we have reported any new errata.

Complete the exam using the exam1.rkt starter source code. Please rename this file to 000000.rkt, but replace 000000 with your assigned random number.

Problem 1: Counting the Largest Values

Topics: numeric values, writing procedures

Write, but do not document, a procedure (num-largest x y z) that takes three numbers x, y, and z as input, and returns the number of values that are tied for largest value. Your procedure does not need to work if any of the parameters are zero or negative. The following example outputs may be helpful:

> (num-largest 100 4 2)
1
> (num-largest 50 50 50)
3
> (num-largest 5 2 2)
1
> (num-largest 1 3 3)
2

Note: You may use lambda, section, and compose to implement this procedure, but you may not use if, which we have not yet covered in class.

Problem 2: Bounded Ratings

Topics: numeric values, writing procedures, section, compose

Without using lambda, write and document a procedure (bound-rating rating) that takes one input, a real number that we’ll call rating, and returns:

  • 0, if rating < 0
  • 10, if rating > 10
  • rating, if neither of the two previous conditions holds.

Note that to define this procedure, you will find it necessary to use compose, section, or both. You will also find it useful to go back and think about how we’ve bounded values in past exercises. You may not use if, since we have not yet covered this in class.

Problem 3: Boost the Dominant Component(s)

Topics: irgb colors, image-variant

Consider the following procedure documentation.

;;; Procedure:
;;;   irgb-boost-dominant
;;; Parameters:
;;;   color, an integer-encoded RGB color
;;; Purpose:
;;;   Adds 32 to each of the dominant RGB components of color 
;;; Produces:
;;;   boosted, an integer-encoded RGB color
;;; Preconditions:
;;;   [No additional]
;;; Postconditions:
;;;   Let max_value = (max (irgb-red color) (irgb-green color) (irgb-blue color))
;;;   Let max_boosted = (min 255 (+ max_value 32))
;;;   If (irgb-red color) = max_value, then (irgb-red boosted) = max_boosted,
;;;   If (irgb-green color) = max_value, then (irgb-green boosted) = max_boosted,
;;;   If (irgb-blue color) = max_value, then (irgb-blue boosted) = max_boosted,
;;;   If (irgb-red color) < max_value, then (irgb-red boosted) = (irgb-red color),
;;;   If (irgb-green color) < max_value, then (irgb-green boosted) = (irgb-green color),
;;;   If (irgb-blue color) < max_value, then (irgb-blue boosted) = (irgb-blue color)

Here is an example of running irgb-boost-dominant on our favorite kitten image:

> (define kitten (image-load "/home/rebelsky/Desktop/kitten.jpg"))
> (image-show kitten)

Kitten Image

> (define boosted-kitten (image-variant kitten irgb-boost-dominant))
> (image-show boosted-kitten)

The same kitten image with the dominant color at each pixel "boosted."

a. Implement the procedure described above. You may use helper procedures for this problem (and is recommended!).

Note: You may use lambda, section, and compose to implement this procedure, but you may not use if, which we have not yet covered in class.

b. Test your procedure on at least two images (using image-variant) and a minimum of three RGB colors.

Problem 4: Granular IRGB Rounding

Topics: irgb colors, section, compose, lambda

Suppose we wish to write a procedure (irgb-granular color) which takes as input an integer-encoded RGB color and outputs a more granular version of the color. In particular, irgb-granular rounds each RGB component down to the nearest multiple of 32. Below are some sample executions of the procedure.

> (irgb->string (irgb-granular (irgb 32 100 70)))
"32/96/64"
> (irgb->string (irgb-granular (irgb 255 0 150)))
"224/0/128"

a. Write, but do not document, the irgb-granular procedure using lambda and name it irgb-granular-a. You may not use section nor compose for this part. You may write helper procedures provided you follow the same guidelines for the helper procedures.

When writing a procedure to transform an integer-encoded RGB color, we commonly find ourselves needing to apply the same modifications to each RGB component of the color. Below is the definition of a function (irgb-apply-proc color proc) which takes as input an integer-encoded RGB color and a procedure as parameters and applies the procedure proc to each RGB component of color.

;;; Procedure:
;;;   irgb-apply-proc
;;; Parameters:
;;;   color, an integer-encoded RGB color
;;;   proc, a procedure that takes and returns an integer
;;; Purpose:
;;;   Make a new irgb color where each component is the result of applying proc to the
;;;   corresponding component of color
;;; Produces:
;;;   result, an integer-encoded RGB color
;;; Preconditions:
;;;   [No additional]
;;; Postconditions:
;;;   (irgb-red result) = (proc (irgb-red color)) bounded between 0 and 255
;;;   (irgb-green result) = (proc (irgb-green color)) bounded between 0 and 255
;;;   (irgb-blue result) = (proc (irgb-blue color)) bounded between 0 and 255
(define irgb-apply-proc
  (lambda (color proc)
    (irgb (proc (irgb-red color))
          (proc (irgb-green color))
          (proc (irgb-blue color)))))

b. Write, but do not document, the irgb-granular procedure using section and compose and name it irgb-granular-b. You may make use of the irgb-apply-proc definition above, but you may not use lambda in any other way in this part. You may write helper procedures provided you follow the same guidelines for the helper procedures.

Problem 5: Whatzitdo?

Topics: documentation, code reading

Sometimes students (and professors) come up with difficult-to-read solutions to arithmetic problems, like the one below.

(define hamster (lambda
    (cat dog) (- (/ (+ 
(min cat dog) (max 
     cat dog)) 2) (min
     cat dog))))

a. Add (or remove) carriage returns and indent the code so that it is formatted clearly.

b. Rename the procedure and the parameters so that they will make sense to the reader.

c. Write 6P-style documentation for the code.

d. Explain how the code achieves its purpose.

Problem 6: Examining Evaluation Order

Topics: I/O, how scheme evaluates expressions

The following procedure computes one of the two outcomes of the quadratic formula:

(define quadratic1
  (lambda (a b c)
    (/ (+ (- b) (sqrt (- (expt b 2) (* 4 a c)))) (* 2 a))))

As you saw in lab, we can write our own versions of the procedures used in this expression, such as sqrt_* and multiply_*, that compute the same value but also produce output in the interactions pane to tell us when they execute. This allows us to determine exactly how Scheme executes this expression.

a. Write logging versions of all of the procedures used above: /, *, +, -, sqrt, and expt. Hint: You may need to write multiple versions of multiply_* that take different numbers of parameters. For example, multiply3_* could multiply three values, while multiply2_* would multiply just two values.

b. Write a new version of quadratic that uses these logging procedures. You do not need to document these logging procedures.

c. Using your new annotated version of quadratic, report the order in which scheme evaluates all the sub-expressions in quadratic.

Questions and Answers

We will post answers to questions of general interest here while the exam is in progress. Please check here before emailing questions!

General Questions and Answers

What is a general question?
A question that is about the exam in general, not a particular problem.
Do the two sections have the same exam?
Yes.
Can we still invoke the “There’s more to life” clause if we spend more than five hours on the exam?
Yes. However, we really do recommend that you stop at five hours unless you are very close to finishing. It’s not worth your time or stress to spend more effort on the exam. It is, however, worth your time to come talk to us, and perhaps to get a mentor or more help (not on this exam, but on the class). There’s likely some concept you’re missing, and we can help figure that out.
What do you mean by “implement?”
Write a procedure or procedures that accomplish the given task.
Do we have to make our code concise?
You should strive for readable and correct code. If you can make it concise, that’s a plus, but concision is secondary to readability and correctness. Long or muddled code is likely to lose points, even if it is correct.
Much of your sample 6P-style documentation has incomplete sentences. Can we follow that model? That is, can we use incomplete sentences in our 6P-style documentation?
Yes, you can use incomplete sentences in 6P-style documentation.
You tell us to start the exam early, but then you add corrections and questions and answers. Isn’t that contradictory? Aren’t we better off waiting until you’ve answered the questions and corrected any errors?
We think you’re better able to get your questions answered early if you start early. Later questions will generally be told “See the notes on the exam.”
How do we know what our random number is?
You should have received instructions on how to generate your random number on the day the exam was distributed. If you don’t have a number, ask your professor for one before submitting your exam.
To show we’ve tested the code informally, would you just like us to just post the inputs we used to test the procedure? If so, how should we list those?
Copy and paste the interactions pane into the appropriate place in the definitions pane. Select the text. Under the Racket menu, use “Comment out with semicolons.”
Should we include examples and, if so, how do we include them?
You should certainly include examples. We would recommend that you copy and paste them from the interactions pane to right below the problem in the definitions pane, and then comment them out with semicolons. (Select and then choose “Comment out with semicolons” from the “Racket” menu. Do not use “Comment out with a box!”
Should we cite our partner from a past lab or assignment if we use code from a past lab or assignment?
You should cite both yourself and your partner, although you should do so as anonymously as possible. For example “Ideas taken from the solution to problem 7 on assignment 3 written by student 641321 and partner.”
If we write a broken procedure and replace it later, should we keep the previous one?
Yes! This will help us give you partial credit if your final procedure isn’t quite right.

Problem 1

My procedure produces the result 2.0 instead of just 2. Is that okay?
Yes, there are reasonable ways to write the num-largest procedure that will return inexact numbers. You will not lose points if your procedure works this way.

Problem 3

Do we need to cite the source of our images?
Yes.
Do we need to go find two new images to test our procedure?
You can count the kitten image as one of your tests.
My username appears in the path to the image file I opened. How can I make that anonymous?
You can replace your username with student just before turning in your exam.

Problem 4

Should we test our procedure on colors or images?
Either is fine. Testing with colors is a good idea because you can check the answers by hand, but it’s nice to see if your procedure changes an image in the way you expected.

Errata

Here you will find errors of spelling, grammar, and design that students have noted. Remember, each error found corresponds to a point of extra credit for everyone. We usually limit such extra credit to five points. However, if we make an astoundingly large number of errors, then we will provide more extra credit. (And no, we don’t count errors in the errata section or the question and answer sections.)

Errors in the starter code

  1. The starter code file was missing closing parenthesis for irgb-boost-dominant, irgb-granular-a, and quadratic_*. (GM, +1 point)
  2. In an effort to fix the starter code, we inadvertently added too many parentheses to irgb-granular-b. (AM, +1/2 point)

Problem 3

  1. The postconditions was inconsistent in its variable use, alternating between max_boosted and max_value_boosted. (TP, +1/2 point)

Problem 6

  1. The quadratic formula was taking the square root of b^2+4ac instead of b^2-4ac. (+1 point)

Citations

Some of the problems on this exam are based on (and at times copied from) problems on previous exams for the course. Those exams were written by Charlie Curtsinger, Janet Davis, Rhys Price Jones, Samuel A. Rebelsky, John David Stone, Henry Walker, and Jerod Weinman. Many were written collaboratively, or were themselves based upon prior examinations, so precise credit is difficult, if not impossible.

Some problems on this exam were inspired by conversations with our students and by correct and incorrect student solutions on a variety of problems. We thank our students for that inspiration. Usually, a combination of questions or discussions inspired a problem, so it is difficult and inappropriate to credit individual students.