Skip to main content

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 csc151 package.
  • Require the csc151 package 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 by latitude and longitude.
  • 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.