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 exam2.rkt starter source code.
Topics: Booleans and Predicates, Conditionals
We have seen a number of different ways to conditionally execute Scheme code in this course.
For this problem, you will use three different techniques to implement a procedure that finds the median of three values.
You will first write documentation for a
median3 procedure that should apply to all of your implementations.
Consider the following example uses of
> (median3 1 2 3) 2 > (median3 -100 5 6) 5 > (median3 3 3 4) 3 > (median3 15.6 19.2 128) 19.2 > (median3 19 2 145) 19
You will implement this procedure three different ways: using
cond, and finally using short-circuit evaluation.
Your implementations may only use numeric constants,
- unless otherwise specified below.
a. Write 6P-style documentation for the procedure
(median3 x y z). This procedure should return the median value of the three numeric parameters.
b. Write, but do not document, the procedure
(median3-if x y z), which should find the median of three values using at least one
if. In addition to the
if expression(s), you may only use the procedures and syntax listed above.
c. Write, but do not document, the procedure
(median3-cond x y z), which should find the median of three values using
cond. In addition to the
cond expression(s), you may only use the procedures and syntax listed above.
d. Write, but do not document, the procedure
(median3-short-circuit x y z), which should find the median of three values using the short-circuit evaluation of
or. You may only use the procedures and syntax listed at the top of this problem.
Topics: Tables, Heterogeneous Lists
Many of the datasets we will look at in this class contain far more information than what we need for specific tasks.
Sometimes this information is contained in extra rows of a table that we can filter out, but other times a table will contain unnecessary columns.
Write and document a procedure
(select-columns table column-indices) that takes a
table as input along with a list of numbers called
This procedure should then produce a table that contains only the requested column indices.
The following examples all use the US ZIP Code dataset from the reading data from files lab.
The examples assume you have the file
us-zip-codes.csv on your desktop.
> (define zips (read-csv-file "~/Desktop/us-zip-codes.csv")) > (take (select-columns zips (list 0 1 2)) 3) '(("00501" 40.922326 -72.637078) ("00544" 40.922326 -72.637078) ("00601" 18.165273 -66.722583)) > (take (select-columns zips (list 0 3 4)) 3) '(("00501" "Holtsville" "NY") ("00544" "Holtsville" "NY") ("00601" "Adjuntas" "PR")) > (take (select-columns zips null) 3) '(() () ()) > (take (select-columns zips (list 5)) 3) '(("Suffolk") ("Suffolk") ("Adjuntas"))
Do not forget to test your procedure carefully. You are required to show at least three additional example uses of your procedure to receive full credit on this problem.
Reminder: List and column indices start at zero in Scheme.
Request: Please do not include your username in the examples. You can replace your username with “student” after running your examples, or use the “~” character to refer to your home directory without using your username as in the examples above.
Topics: lists, local bindings, code reading, documentation
Consider the following interesting procedure definition.
(define s (lambda (l) (let ([a (iota (length l))]) (let ([a (map even? a)]) (let ([a cadr] [b (map list l a)]) (let* ( [c (filter a b)]) (list (map car c) (map car (filter (negate cadr) b)))))))))
Determine what this procedure does and then do the following.
a. Reformat the procedure so that it follows reasonable standards. (You need not show this version; we only want to see the version in part b.)
b. Rename the procedure, parameters, and local variables so that they will make sense to the reader.
c. Write 6P-style documentation for the renamed procedure.
d. Explain how the procedure achieves its goal.
Topics: Reading Data from Files, Heterogeneous Lists, Tables, Predicates, Conditionals, Displaying Data
We collect large datasets for different purposes and use them to predict some possibilities or generate new information.
For this experiment, we will be using a dataset extracted by Barry Becker from the 1994 Census database, originally obtained from the UCI Machine Learning Repository.
The dataset is available in the file
The original use for this dataset was to build a model that predicts whether an individual will make over $50,000 a year based on a collection of attributes.
You can read about the dataset and see a list of attributes in the dataset’s codebook
First, write code to load the dataset into a table.
You do not need to put the loading or selecting code into a procedure;
you can just define a variable
census that will hold the data from this dataset.
In preparation for plotting our dataset, write Scheme code that allows you to count the number of individuals listed as Male or Female in one of the other categories. For example, you could report the number of Male and Female individuals in each working class, education level, marital status, or race. You will likely want to write a procedure to help with this process. If you do so, please document this procedure with 4Ps. Please include the results produced by your counting procedure in your example output for this problem.
You will be plotting the results from your counting procedure using a histogram. Your counts will need to be in a specific format to support plotting. For example, this output shows the expected counts for each workclass, broken down by sex; in this case, the first number is the count of male individuals in the group, and the second count is the number of female individuals in the group. Your solution must produce data in this form automatically; a solution that requires you to manually copy values into a data format will not receive full credit.
'(("State-gov" (809 489)) ("Self-emp-not-inc" (2142 399)) ("Private" (14944 7752)) ("Federal-gov" (645 315)) ("Local-gov" (1258 835)) ("?" (997 839)) ("Self-emp-inc" (981 135)) ("Without-pay" (9 5)) ("Never-worked" (5 2)))
Present your results with a stacked histogram plot. You should include the code to generate the plot from the original dataset in your submission; I will re-run the code to generate the plot. The example output below shows the plot for the example data in the previous part.
You may find it useful to adjust the plot width using the optional
#:width parameter to
plot, especially if you choose a dataset variable with many possible values.
Finally, explain in 4–5 sentences what this plot tells you about the dataset, the individuals in the dataset, or the types of observations in the dataset.
Topics: Lists, Recursion, Checking Preconditions
We have seen procedures to check if a list contains a particular value, or to find the location of a value.
We might also like to know how many times a particular value appears in a list.
You can imagine that this procedure would be a useful building block for
Write and document the procedure
(count-occurrences lst val), which returns the number of times
val appears in
Your implementation must check all preconditions in addition to specifying them in your 6P-style documentation.
Your procedure must produce the following example output. Do not forget to come up with at least three of your own examples to check your implementation.
> (count-occurrences (list 1 2 1 3 1 4 1 5 1 6) 1) 5 > (count-occurrences (iota 5) -1) 0 > (count-occurrences "hello" #\l) Error! Error: count-occurrences expected a list for the first parameter. > (count-occurrences (string->list "hello") #\l) 2 > (count-occurrences (list 3 3.0 (+ 1 2)) 3) 2 > (count-occurrences (list "hello" "world" "hello" "class" "hello" "exam2") "hello") 3
Hint: While the
(list-contains lst val) procedure we saw in class used recursion, you do not necessarily have to use recursion in your solution.
We will post answers to questions of general interest here while the exam is in progress. Please check here before emailing questions!
median3-_always be in ascending order?
select-columnsprocedure have to work for any kind of data?
letto bind that expression with a name. You do not need to remove anything to receive full credit on this problem if you can make the code readable.
letrec. You can read ahead and use this if you like.
#|before the pasted material. Put a
|#after the pasted material.
|#or semicolons. You might also add a note or two as to what you were trying to do.
list-ref? I’d swear we’ve used it, but I can’t find where.
lambdathat looks like
(define (proc params) body). Can I use that?
(random 1000000). If you end up with a number less than six digits, add zeros to the left side of the number until you have six digits.
; STUBon some of the procedures. What does that mean?
Please check back periodically in case we find any new issues.
median3as the procedure instead of
select-columns. [+1 point]
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.