Exam 1: Scheme basics
Assigned: Wednesday, February 8
Prologue Due: Friday, February 10 by 10:30pm
Exam Due: Tuesday, February 14 by 10:30pm
Epilogue Due: Wednesday, February 15 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: Adding three
Topics: documentation, defining procedures with compose, defining procedures with section, defining procedures with lambda
We have now learned three different ways to write procedures.
-
We can use function composition.
-
We can use sectioning.
-
We can use
lambda
.
a. Write the 6P-style documentation for a procedure, add3
, that
adds three to its argument.
b. Implement add3
using function composition. To avoid name
overlap, you can call this add3b
. You may not use sectioning,
lambda
, or other procedures you define in implementing add3b
.
c. Implement add3
using sectioning. To avoid name overlap, you
can call this add3c
. You may not use composition, lambda
, or
other procedures you define in implementing add3c
.
d. Implement add3
using lambda
. To avoid name overlap, you can
call this add3d
. You may not use sectioning, composition, or
other procedures you define in implementing add3d
.
Problem 2: Increasing contrast
Topics: irgb colors, writing procedures, image-variant
Sometimes an image can look “washed out” if the difference between light and dark colors is not sufficiently large. We can increase the contrast of an image by increasing the magnitude of bright color components and decreasing the magnitude of darker color components.
Write, but do not document, a procedure (irgb-increase-contrast color amount)
. This procedure should return a new color which we will call result
. If the red component of color
is less than 128, the red component of result
should be less than that of color
. If the red component of color
is greater than 128, then the red component of result
should be larger than that of color
. The same rules apply to the green and blue components.
The amount
parameter should control how much the components change, but the exact meaning of this parameter is up to you. The one requirement is that a larger value for amount
should result in a larger change in each component.
Here is an example run of irgb-increase-contrast
:
> (define kitten (image-load "/home/rebelsky/Desktop/kitten.jpg"))
> (define contrast-kitten
(image-variant kitten (section irgb-increase-contrast <> 1.6))
Here is the original image:
> (image-show kitten)
And here is one example of the kitten with increased contrast.
> (image-show contrast-kitten)
Note: your implementation may produce different results for a given amount
. You may submit any implementation where increasing amount increases the change in contrast.
Problem 3: Whatzitdo?
Topics: arithmetic operators, code reading, documentation
Sometimes students (and professors) come up with difficult-to-read solutions to simple problems, like this one below:
(define z (lambda
(w x y) (-
(+ w y (* 2 x))
(min w x y) x (max w x y))))
a. Clean up this procedure. You should reformat the code (add carriage returns and indent to format clearly); rename the procedure, parameters, and variables; and simplify any unnecessarily complicated code.
b. Write 6P-style documentation for the code.
c. Explain how the code achieves its purpose.
Problem 4: Shades
Topics: RGB colors, Color transformations, lambda
Recall that on a recent assignment, you wrote a procedure that did “gamma correction” on images. If we do gamma correction on a single color, we get something that might be called a “shade” of that color. (Our colleage in Studio Art, Matt Kluber, says that there is no such thing as a “shade”, but you know what we mean.)
Write, but do not document, a procedure, (shades color)
, that
takes as input an integer-encoded RGB color and produces a swatch
of five colors:
- the color gamma corrected by 0.5,
- the color gamma corrected by 0.75,
- the color gamma corrected by 1.0,
- the color gamma corrected by 1.25, and
- the color gamma corrected by 1.5.
If you were not able to implement gamma correction, contact your instructor for a solution.
Problem 5: Adding times, revisited
Topics: code reading, representing times, complex numbers, numeric computation, abusing Scheme
Suppose we want to do math with times, and we limit ourselves to times that involve minutes and seconds. How do we represent both minutes and seconds? Here’s a not-necessarily-clever trick: We could use complex numbers. The real part of the imaginary number represents the minutes and the imaginary part represents the seconds.
Here are some procedures that allow us to work with that representation.
;;; Procedure:
;;; time
;;; Parameters:
;;; min, a non-negative integer
;;; sec, a non-negative integer
;;; Purpose:
;;; Generate a representation of min minutes and sec seconds
;;; Produces:
;;; tm, a complex number representing a time
;;; Preconditions:
;;; [No additional]
;;; Postconditions:
;;; (minutes tm) = min
;;; (seconds tm) = sec
(define time
(lambda (min sec)
(+ min (* 0+i sec))))
;;; Procedure:
;;; minutes
;;; Parameters:
;;; tm, a complex number representing a time
;;; Purpose:
;;; Extract the minutes from tm
;;; Produces:
;;; min, an integer
(define minutes real-part)
;;; Procedure:
;;; seconds
;;; Parameters:
;;; tm, a complex number representing a time
;;; Purpose:
;;; Extract the seconds from tm
;;; Produces:
;;; sec, an integer
(define seconds imag-part)
;;; Procedure:
;;; display-time
;;; Parameters:
;;; tm, a complex number representing a time
;;; Purpose:
;;; Display the time.
;;; Produces:
;;; [Nothing; called for the side effect]
(define display-time
(lambda (tm)
(display (minutes tm))
(display " minutes and ")
(display (seconds tm))
(display " seconds.")
(newline)))
Write and document a procedure, (add-times time1 time2)
, that
adds the two times appropriately. For example,
> (define t1 (time 5 35))
> (minutes t1)
5
> (seconds t1)
35
> (display-time t1)
5 minutes and 35 seconds.
> (define t2 (add-times t1 t1))
> (minutes t2)
11
> (display-time t2)
11 minutes and 10 seconds.
> (display-time (add-times t1 t2))
16 minutes and 45 seconds.
Your procedure should correctly limit the number of seconds to between 0 and 59, even if the input time is not in that form.
> (define t3 (time 0 97))
> (display-time t3)
0 minutes and 97 seconds.
> (define t4 (add-times t3 t3))
> (display-time t4)
3 minutes and 14 seconds.
> (display-time (add-times (time 0 0) t3))
1 minutes and 37 seconds.
Problem 6: Flattening
Topics: RGB colors, color transformations, clever numeric computation
A common technique for manipulating images is known as “flattening” the image. In general, we flatten an image by restricting the values of each component to multiples of a certain value. For example, we might ensure that the components are each multiples of 16, 32, or 64. (We’ll use 255 instead of 256 for the highest multiple.)
a. Write and document a procedure, (irgb-flatten irgb-color val)
,
that flattens an IRGB color by converting each component to the
nearest multiple of val
.
> (define c1 (irgb 74 179 221))
> (irgb->string (irgb-flatten c1 10))
"70/180/220"
> (irgb->string (irgb-flatten c1 64))
"64/192/192"
If the nearest multiple is over 255, you can rely on the irgb
procedure to convert it to 255.
> (irgb->string (irgb-flatten (irgb 77 23 252) 100))
"100/0/255" ; The nearest multiple of 100 to 252 is 300.
b. Using irgb-flatten
, write, but do not document, a procedure
(image-flatten image val)
that flattens an image by flattening
each pixel in the image so that each component is converted to the
nearest multiple of val
.
You will receive a modicum of extra credit if you can define
irgb-flatten
or image-flatten
without relying on lambda
.
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.
- What is the symbol
'STUB
that appears throughout the exam file? - We use the term
'STUB
when we need to fill in a placeholder in code for what you are going to write in the exam. - How should I fill out the time log?
- Something like the following.
; Time Log:
; Date Start Finish Elapsed Activity
; 2017-02-08 14:00 14:15 0:15 Tried to understand problem, wrote prelim docs
; 2017-02-09 18:00 18:20 0:20 Finished documenting
; 2017-02-09 19:00 19:20 0:20 Draft of procedure. Works for most cases, but not black and white.
; 2017-02-10 01:00 01:10 0:10 Woke up in the middle of the night with the solution
; 2017-02-10 09:00 09:05 0:05 Minor cleanup
; Time Spent: 1:10
Questions on problem 1: Adding three
- Can I use
section
in my solution that uses composition? - No. Composition should rely just on composition.
- Any hints on how to solve this using composition?
- Review the reading that introduced composition.
Questions on problem 2: Increasing contrast
- Can I change the preconditions to require that
amount
is greater than - one?
- Yes.
- Can I require that the components be neither 0 nor 255 for me to increase
- the contrast?
- Yes. We’ve revised the postconditions to make that clear.
Questions on problem 5: Adding times, revisited
- Can we use the provided procedures?
- You should use the provided procedures.
- Any other hints?
- Try expressing the result in English. “If I add t1 and t2, the number of minutes in the result should be … and the number of seconds should be ….”
- I’m not sure that I understand complex numbers.
- You don’t need to worry about the complex numbers. You should never deal with them directly.
- I don’t understand why it says that
display-time
produces “[Nothing; called for the side effect]”. - It’s one of those output vs. return issues. Consider the following releated procedures.
(define p1
(lambda (val)
(display "[")
(display val)
(display "]")
(newline)
val))
(define p2
(lambda (val)
(display "{")
(display val)
(display "}")
(newline)))
Both p1
and p2
display val
with symbols around it. But p1
then
returns (produces) the same value it was given, while p2
returns
(produces) nothing. We can see the difference if we try to use them.
> (+ 1 (p1 5))
[5]
6
> (+ 1 (p2 5))
{5}
. . +: contract violation
expected: number?
given: #<void>
argument position: 2nd
other arguments...:
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.)
Problem 2: Increasing contrast
- The line
(define kitten (image-load "/home/rebelsky/Desktop/kitten.jpg"))
was missing a right parenthesis. [+1 YC] - The postconditions, as stated in the file, are impossible to acheive for components of 0 or 255 [+0 CM]
Problem 3: Whatzitdo?
- Carriage return was mispelled. [+1 IX]
Problem 5: Adding times, revisited
- In the sample code, an “add times” was supposed to be “add-times,” and the output “0 minutes and 96 seconds” was supposed to be “0 minutes and 97 seconds.” [+1 RL]
Problem 6: Flattening
- The wording “A common common” should have been “A common” instead. [+1 MT,AH]
- One occurrence of “irb-flatten” should have been “irgb-flatten” [+1 MT]
- The output of
(irgb->string (irgb-flatten c1 64))
should have been"64/192/192"
instead. [+0 IX]
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, Titus Klinge, 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.