Conditionals
Summary: In this lab, you will have the opportunity to explore Scheme’s
three primary conditional control operations, if, when, and cond.
Preparation
a. Do the traditional lab preparation. That is,
- Start DrRacket.
- Check for update the
csc151package. - Require the
csc151package with(require csc151).
b. Load the list of cities arranged by zip codes.
(define zips (read-csv-file "/home/username/Desktop/us-zip-codes.csv"))
c. Add the following undocumented procedure to your definitions pane.
(define zip-ends-with
(lambda (city three-char-suffix)
(string=? (substring (car city) 2) three-char-suffix)))
d. Figure out what zip-ends-with does. You may also want to add a
note to yourself for when you come back to it later.
e. Create a small subset of the zips data using filter and
zip-ends-with.
(define some-zips
(filter ... zips))
Exercises
Exercise 1: Who won?
Define and test a Scheme procedure, (report-victory score), that takes
one argument, a real number, and returns the symbol won if score is
positive, the symbol lost if it is negative, and the string tied
if it is zero.
a. Use if for all the tests within your procedure.
b. Use cond for all the tests within your procedure.
Exercise 2: Categorizing values
In the reading, we started to write a procedure that categorized values. Let’s extend that example.
Write a procedure, (type-of val), that returns
- the symbol
'boolean, if val is a boolean; - the symbol
'character, if val is a character; - the symbol
'number, if val is a number; - the symbol
'procedure, if val is a procedure; - the symbol
'string, if val is a string; - the symbol
'symbol, if val is a symbol; or - the symbol
'miscellaneous, if val is anything else.
Exercise 3: The Sphinx’s Riddle”>
As you may know, one of the famous riddles of the Sphinx goes something like the following:
What is it that walks upon four legs, then two legs, then three legs?
The answer is, of course, humans.
Write a Scheme predicate, legs, that, given someone’s age, tells how
many legs they walk upon. (You get to choose reasonable ages for these
three phases of life.)
Exercise 4: Who won?, revisited
You may recall a previous question that asked for the following:
Define and test a Scheme procedure (report-victory score) that takes
one argument, a real number, and returns the symbol won if score is
positive, the symbol lost if it is negative, and the string tied
if it is zero.
In that problem, you wrote one version that used if and one version
that used cond. However, it is also possible to write report-victory
using only and, or, and not. Try doing so.
Exercise 5: Validating Dates
Write a procedure, (valid-date? month day), that returns #t if
the numbers month and day describe a valid month and day and false
otherwise. For example,
> (valid-date? 1 30)
#t
> (valid-date? 2 30)
#f
> (valid-date? 9 30)
#t
> (valid-date? 9 31)
#f
> (valid-date? 9 -1)
#f
> (valid-date? 9 250)
#f
a. Write this procedure using if as the primary control structure.
b. Write this procedure using cond as the primary control structure.
c. Write this procedure without if and cond (that is, using and,
or, and, possibly, not).
Exercise 6: Describing locations
In the corresponding reading, you saw a procedure that returns “North” for a latitude north of 39.72 and “South” for a latitude south of 39.72.
a. Rewrite that procedure so that it takes a full zip-code entry as input and produces
- The string
"Unknown"if there is no latitude. - The string
"Border"if the latitude is exactly 39.72. - The string
"North"if the latitude is greater than 39.72. - The string
"South"if the latitude is less than 39.72.
For example
> (categorize-city '("09123" "" "" "Apo" "AE" ""))
"Unknown"
> (categorize-city '("02123" 42.338947 -70.919635 "Boston" "MA" "Suffolk"))
"North"
> (categorize-city '("25123" 38.704805 -81.914474 "Leon" "WV" "Mason"))
"South"
b. Using map1, apply this procedure to every element of the
some-zips list you created in the preliminaries.
c. Using map1 and tally, determine how many cities are in
some-zips are classified in each way.
d. Determine how many cities in zips are classified in each way.
Note that we asked you to try the shorter list first because you should generally experiment with small sets of data to make sure that your procedure is correct before running it on a larger list.
Exercise 7: Describing locations, again
You probably noticed that there are no cities exactly on the border between north and south. Rewrite the procedure from exercise 6 so that it takes a full zip-code entry as input and produces
- The string
"Unknown"if there is no latitude. - The string
"Border"if the latitude is between 39.70 and 39.74. - The string
"North"if the latitude is greater than 39.74. - The string
"South"if the latitude is less than 39.70.
Redo the remaining steps of exercise 6.
For those with extra time
Extra 1: Describing locations, yet again
Write a procedure, (relative-to row latitude longitude) that
returns
- The string
"N"if the row describes a city that is primarily north of the location described bylatitudeandlongitude. - The string
"S"if the row describes a city that is primarily south of that location. - The string
"E"if the row describes a city that is primarily east of that location. - The string
"W"if the row describes a city that is primarily west of that location. - The string
"NE"if the row describes a city that is primarily northeast of that location. - The string
"NW"if the row describes a city that is primarily northwest of that location. - The string
"SE"if the row describes a city that is primarily southeast of that location. - The string
"SW"if the row describes a city that is primarily southwest of that location. - The string
"*"if the row describes a city that is close to that location. - The string
"?"if the row describes a city with no latitude or longitude.
You may determine your own criteria for these different categories, provided that they are reasonable. For example, a city that is 500 miles west and 1 mile north of a location should be classified as “W” and not “NW”.
Extra 2: Relative to the center
Wikipedia tells us that the geographic center of the continental US is at 39°50′N 98°35′W. In the notation we’ve been using, that’s a latitude of about 39.83 and a longitude of about -98.58.
a. Find the zip code closest to that location.
b. Find out how many zip codes are in each direction from that location.
c. Write a procedure, (add-relative-position row), that adds the
relative position of a city to end of the entry for that city.
> (add-relative-position '("25123" 38.704805 -81.914474 "Leon" "WV" "Mason"))
'("25123" 38.704805 -81.914474 "Leon" "WV" "Mason" "E")
> (add-relative-position '("09123" "" "" "Apo" "AE" ""))
'("09123" "" "" "Apo" "AE" "" "?"))
Notes
Notes on exercise 4
To write the procedure report-victory without if and cond, we
need to take advantage of the way and and or behave. Recall that
and either returns false (if it encounters a false) or the last value
(if it fails to encounter a false value) and that or returns the first
non-false value, if one is there.
Hence, we’ll use an and for each test and group them together within an
or.
The first test looks something like this: (and (> score 0) 'won).
Note that this test returns #f if score is less than or equal to 0
and the symbol won otherwise.
We can then put that in an or expression. Here’s a start.
(or (and (> score 0) 'won)
'something-else)
Now, if score is greater than 0, we get won and
otherwise we get something-else.
The remainder is up to the reader to figure out.