Lab 2: Conditionals and Reading Code

9 September 2022

The purpose of this lab is to give you practice:

  • using Boolean expressions,
  • reading and writing if expressions,
  • writing functions that use if expressions, and
  • writing examples/tests for the functions you write.

For this lab, you’re encouraged to work with a partner, but it can be completed individually if you prefer.

You’ve been asked to review a program written by a coworker. The problem they were asked to solve was to turn a numeric grade into its corresponding letter grade.

Your coworker shows you this solution:

fun grade(percent :: Number) -> String:
  doc: "Return the letter grade for a percent."
  if percent > 0:
    "F"
  else if percent >= 60:
    "D"
  else if percent >= 70:
    "C"
  else if percent >= 80:
    "B"
  else if percent >= 90:
    "A"
  end
end

Task: Answer the following questions in multi-line Pyret comment, like

#|
   This is my answer...
   continuing ...
   as long as I need it to!
|#
  • Write down an example where the code does not return what you think it should.

  • Why doesn’t this solution work as intended?

  • Why wouldn't your coworker realize this function isn’t right? What should they have done?

Consider making a simple weather app that alerts users of severe weather based on wind speed using the Saffir–Simpson scale:

Category Wind Speed (mph)
5 ≥ 157
4 130–156
3 111–129
2 96–110
1 74–95
Tropical storm 39–73
Tropical depression ≤ 38

Task: Write a function that takes in the average recorded recent wind speed (in miles per hour) and returns the category to which that wind speed belongs:

fun saffir-simpson(wind-speed :: Number) -> String:
  ...
end

Here are some examples of the desired behavior of the saffir-simpson function:

››› saffir-simpson(65)
"Tropical storm"
››› saffir-simpson(111)
"Category 3"
››› saffir-simpson(0)
"Tropical depression"

You can assume all inputs are integers (that is, no decimals or fractions). Be sure to write tests for your function that address each category.

For your weather app, you want to get alerts only about weather happening where you are – at Vassar!

Task: Write the function

fun at-vassar(latitude :: Number, longitude :: Number) -> Boolean:
  ...
end

It should return true if the specified latitude and longitude correspond roughly to the Vassar campus, with

  • latitude between 41.656 and 41.693
  • longitude between -73.908 and -73.880

For testing, you may want to use the coordinates

  • (41.686804, -73.895664): Main Building
  • (34.119108, -118.300388): The Griffith Observatory, Los Angeles

For your weather app, you wish to get a severe weather notification if the wind speed is classified as a hurricane (Category 1–5) and the classification is for Vassar.

Task: Write the function

fun severe-alert(wind-speed :: Number, latitude :: Number,
    longitude :: Number) -> Boolean:
  ...
end

It takes the current wind speed and the location of the wind (latitude and longitude), and returns true if the storm is a categorized hurricane (1–5) and over Vassar, and false otherwise.

Here are some tests you can try (or make your own!):

# Hurricane at Main Building
severe-alert(190, 41.686804, -73.895664) is true
# Gentler weather at Main Building
severe-alert(10, 41.686804, -73.895664) is false
# Hurricane at the Griffith Observatory, Los Angeles
severe-alert(190, 34.119108, -118.300388) is false

Your severe-alert function should call the at-vassar function you just wrote!

On the other hand, maybe you have a relaxed attitude toward danger, and you only to only get an alert if the storm is the worst type (Category 5) and over Vassar.

Task: Write the function

fun extreme-alert(wind-speed :: Number, latitude :: Number,
    longitude :: Number) -> Boolean:
  ...
end

It works the same way as the previous function, but only returns true if the wind speed is "Category 5".

Consider how this function would differ from severe-alert. Can you think of a way you can use the saffir-simpson function you’ve already written to avoid duplicate code?

Oh no – your coworker’s back!

They’ve been asked to write a function to compute the price for a newspaper ad based on the number of characters (that is, letters, numbers, spaces, and punctuation).

This time they’re sure the function works right, and they have test cases to prove it. But, the result is … not pretty:

fun ad-charge(ad):
  short-length = 10
  medium-length = 40
  long-length = 70
  if ((string-length(ad) >= short-length) and (string-length(ad) < medium-length)):
    (string-length(ad) * (short-length / 2)) + (string-length(ad) * 5)
  else if ((string-length(ad) >= medium-length) and (string-length(ad) < long-length)):
    (string-length(ad) * (medium-length / 2)) + (string-length(ad) * 5)
  else if (string-length(ad) >= long-length) :
    (string-length(ad) * (long-length / 2)) + (string-length(ad) * 5)
  else: 0
  end
where:
  ad-charge("Big Sale!") is 0
  ad-charge("End of Year Clearance") is 210
  ad-charge("End of Year Clearance -- Buy! Buy! Buy! Buy!") is 1100
end

Task: Rewrite ad-charge to follow good Pyret style (see our guide). Do your best to make the code clear and avoid repetition. But don’t change how it works – the provided test cases should still pass!

  • When you’ve completed the exercises, show your code to your instructor or one of the coaches.

  • Then upload your lab02.arr file to the Lab 2 assignment on Gradescope. If you worked with a partner, submit a single copy of the lab with both your names. (See these instructions.)

This lab includes material adapted from Kathi Fisler and colleagues at Brown University.