# Boolean values, predicate procedures, and list filters

*Summary:* In this laboratory, you will have the opportunity to explore a number of issues relating to predicates, Boolean values, conditional operations, and list filters.

## 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 by with zip codes.

```
(define zips (read-csv-file "/home/username/Desktop/us-zip-codes.csv"))
```

## Exercises

### Exercise 1: Writing your own predicates

a. Write a unary predicate, `in-iowa?`

, that takes one row (element) from the
collection of cities and returns `#t`

if that element is in Iowa and
`#f`

otherwise.

```
> (in-iowa? '("50112" 41.685324 -92.630258 "Grinnell" "IA" "Poweshiek"))
#t
> (in-iowa? '("50208" 41.718107 -93.012335 "Newton" "IA" "Jasper"))
#t
> (in-iowa? '("02158" 42.385096 -71.208399 "Newton" "MA" "Middlesex"))
#f
```

b. Write a unary predicate, `has-longitude?`

, that takes one row
(element) from the collection of cities and returns `#t`

if that element
has a numeric longitude and `#f`

otherwise.

```
> (has-longitude? '("04236" 44.189655 -70.136683 "Greene" "ME" "Androscoggin"))
#t
> (has-longitude? '("98282" "" "" "Camano Island" "WA" "Island"))
#f
```

c. Write a unary predicate, `missing-latitude?`

, that takes one row
(element) from the collection of cities and returns `#t`

if that element
lacks a numeric latitude and `#f`

otherwise.

```
> (missing-latitude? '("04236" 44.189655 -70.136683 "Greene" "ME" "Androscoggin"))
#f
> (missing-latitude? '("98282" "" "" "Camano Island" "WA" "Island"))
#t
```

### Exercise 2: Predicates with comparisons

a. Write a unary predicate, `west-of-grinnell?`

, that holds only when
an entry is strictly west of Grinnell, which has longitude -92.630258.
You may assume that the entry has a real number in the longitude position.

```
> (west-of-grinnell? '("60637" 41.811929 -87.68732 "Chicago" "IL" "Cook"))
#f
> (west-of-grinnell? '("92222" 32.782242 -114.561905 "Bard" "CA" "Imperial"))
#t
> (west-of-grinnell? '("98282" "" "" "Camano Island" "WA" "Island"))
. . ../../Applications/Racket v6.5/collects/racket/private/kw.rkt:929:25: <: contract violation
expected: real?
given: ""
argument position: 1st
other arguments...:
```

b. Write a unary predicate, `in-narrow-band?`

, which holds only when
an entry has a longitude between -90.3 and -96.5, exclusive. You may
assume that the entry has a numeric longitude.

```
> (in-narrow-band? '("55460" 45.015914 -93.47188 "Minneapolis" "MN" "Hennepin"))
#t
> (in-narrow-band? '("68524" 40.879252 -96.815309 "Lincoln" "NE" "Lancaster"))
#f
```

### Exercise 3: Some simple filters

a. Using `filter`

and `in-iowa?`

, create a list of all the cities in Iowa
that are in the `zips`

table.

b. Using that filtered list, find how many zip codes there are in Iowa.

c. Using `filter`

and `missing-latitude?`

, Create a list of all the
entries in `zips`

that lack a latitude.

### Exercise 4: More filters

a. What do you expect to happen if you filter `zips`

using
`west-of-grinnell?`

, as in the following?

```
> (define zips-wog (filter west-of-grinnell? zips))
```

b. Check your answer experimentally.

c. As you likely predicated and found, the `west-of-grinnell?`

predicate
can’t work on cities that lack a longitude. Write a new predicate,
`wog?`

, that is like `west-of-grinnell?`

, but also returns `#f`

if the
row (entry) lacks a longitude.

### Exercise 5: Exploring `and`

a. What value do you expect to get for `(and "one" 2 'three)`

?

b. Check your answer experimentally.

c. What value do you expect to get for `(and "one" 2 #f 'three)`

?

d. Check your answer experimentally.

e. What value do you expect to get for `(and "one" 2 #t 'three)`

?

f. Check your answer experimentally.

g. What value do you expect to get for `(and "one" 2 'three #t)`

?

h. Check your answer experimentally.

i. What value do you expect to get for `(and 1 2 3)`

?

j. Check your answer experimentally.

k. Describe, in your own words, the policy that leads to those results.

### Exercise 6: Exploring `or`

a. What value do you expect to get for `(or "one" 2 'three)`

?

b. Check your answer experimentally.

c. What value do you expect to get for `(or "one" 2 #f 'three)`

?

d. Check your answer experimentally.

e. What value do you expect to get for `(or "one" 2 #t 'three)`

?

f. Check your answer experimentally.

g. What value do you expect to get for `(or "#f" "one" 2 'three)`

?

h. Check your answer experimentally.

i. What value do you expect to get for `(or "#t" "one" 2 'three)`

?

j. Check your answer experimentally.

k. What value do you expect to get for `(or 1 2 3)`

?

j. Check your answer experimentally.

m. Describe, in your own words, the policy that leads to those results.

### Exercise 7: Further explorations of `and`

and `or`

a. Determine the value `and`

returns when called with no parameters.

b. Explain why you think the designers of Scheme had `and`

return that value.

c. Determine the value `and`

returns when called with one, two, and three integers as parameters.

d. Explain why you think the designers of Scheme had `and`

return that value.

e. Determine the value `or`

returns when called with no parameters.

f. Explain why you think the designers of Scheme had `or`

return that value.

g. Determine the value `or`

returns when called with only integers as parameters.

h. Explain why you think the designers of Scheme had `or`

return that value.

If you are puzzled by some of the answers, you may want to look at the notes on this problem.

### Exercise 8: Combining predicates with `negate`

, `conjoin`

, and `disjoin`

.

The second self check in the reading on filtering lists asked you to identify the purpose of a variety of predicates.

Write predicates with equivalent purposes that are intended to work with the zip code data, rather than the capital data. Add a one-line comment to each answer that explains what the predicate computes.

## For Those With Extra Time

### Extra 1: Finding state bounds

Write a procedure, `westernmost`

, that takes two inputs , a list of
cities in the “zip code format” (zip code, latitude, longitude, city,
state, county) and a state abbreviation. It should then produce the longitude
of the westernmost city in that state. You may assume that all of the
cities in the state have valid zip codes.

### Extra 2: Confusing cities

Some city names appear in multipple states. Write a procedure,
`which-states`

, which takes two inputs, a list of cities in the
“zip code” format and a city name. Your procedure should then return
a list of all the states in which that city appears. (It’s okay
if there are duplicates.)

## Notes

### Notes on problem 7

The expression `(and)`

has value true (`#t`

) because “`and`

has a value
of true if none of the parameters have value false”. This call has no
parameters, which means none are false.

Alternately, you can think of `#t`

as the “and-itive identity”. That is, `(and #t x`

) is * x*. When given no parameters,

`and`

returns its identity value.The expression `(or)`

has value false (`#f`

) because “`or`

has value
false if none of the parameters is non-false”. Since this call has no
parameters, none are non-false.

Alternately, you can think of `#f`

as the “or-itive identity”. That is, `(or ... x)`

is * x*. When given no parameters,

`or`

returns its identity value.