Exercise #5

Many American holidays are celebrated on a fixed day of the week, in a week beginning on a specified day. For instance:

Identifying a holiday in this way makes it easy to determine its date in a given year if you are looking at a calendar for that year, with the days arranged in weeks. If you don't have such a calendar for the given year, however, working out the date of the holiday can be a difficult and error-prone task. This makes it suitable for automation.

Part A

Write and test a Scheme procedure that takes the number of a year as its argument and returns the date of Thanksgiving Day in that year. A date can be expressed as a list of three integers, the first giving the number of the year, the second the number of the month within the year, and the third the number of the day within the month. For instance, (1998 11 26) represents November 26, 1998 -- the date of Thanksgiving Day this year. When your procedure is called with the argument 1998, it should return this three-element list.

In order to carry out this computation accurately, you'll need to know exactly when leap years occur in the calendar used in America (the Gregorian calendar). The exact rule is that a year is a leap year if its number is (1) divisible by 400, or (2) divisible by 4 but not by 100. So 1996 was a leap year (under clause 2), and 2000 will be a leap year (under clause 1); but 1998 is not a leap year, and neither was 1900.

Since the Gregorian calendar was adopted in America in 1752, you may assume that only years whose numbers are greater than or equal to 1752 will be given as arguments (and your procedure may call error if this precondition is not met).

Part B

Adapting the procedure you wrote for part A, write and test a Scheme procedure that takes the number of a year as its argument and returns both the date on which Daylight Savings Time begins in that year (Sunday of the week beginning April 1) and the date on which it ends (Sunday of the week beginning October 25).

Part C

Generalizing the code you wrote for parts A and B, write and test a Scheme procedure that takes two arguments, a day of the week (represented by one of the symbols Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, and Saturday) and a date (represented by a three-element list) and returns the date of the specified day in the week beginning on the specified date. (So, for instance, calling this procedure with the arguments Friday and (1998 3 16) should yield (1998 3 20), because March 20, 1998, is the Friday of the week beginning on March 16, 1998.)

Test this procedure carefully -- there are more special cases than you might initially suppose. You may want to work up a list of test cases even before you write the procedure.


This document is available on the World Wide Web as

http://www.math.grin.edu/courses/Scheme/spring-1998/exercise-5.html

created February 26, 1998
last revised June 21, 1998

John David Stone (stone@math.grin.edu)