Lab 3 is due Thursday, October 12 at 11:59pm.
This week, you will practice working with conditional expressions, structures and program design by implementing some common useful operations on calendar dates.
We present a formula for computing the day of the week (below). The formula only works for the 20th and 21st centuries (that is, years, between 1900 and 2099 inclusive), so you will restrict dates to that range.
First, copy the following data definitions from this page.
(define-struct Date ([m : Integer] ;; 1 for Jan, 2 for Feb, ..., 12 for Dec [d : Integer] [y : Integer])) (define-type Day (U 'Sun 'Mon 'Tue 'Wed 'Thu 'Fri 'Sat))
Write a function leap? of type (Integer -> Boolean) to compute whether or not a year is a leap year. Leap years are not simply every fourth year. The precise rule is as follows:
A year is a leap year if it is divisible by 4 and not divisible by 100, or if it isPlease raise an error if the integer argument to leap? is negative. Otherwise, go ahead and crunch the number.divisible by 400.
The constructor Date induced by the Date structure definition builds a value, uncritically, out of any three integers. For example, you could construct the 49th day of December or the 2nd day of the 82nd month, or, for that matter, the -10th month. A constructor that considers whether or not its arguments are reasonable is called a smart constructor. Write a smart constructor to reject any dates that are either not within the 20th or 21st century, or are just nonsensical (like the examples above).
The arguments to this function are the month, day, and year, in that order. The function should return a Date if the arguments are valid, or raise an error otherwise.(: smart-construct-date (Integer Integer Integer -> Date))
Now write two comparison functions, one to test whether two dates are exactly the same, and one to see if, among two dates, the first occurs before the other. These functions should have the following names and types:
(: date=? (Date Date -> Boolean)) (: date<? (Date Date -> Boolean))
We now give the formula for computing the days of the week. We first define a "month adjustment" as follows:
Month Adjustment Jan 0 for leap years, 1 otherwise Feb 3 for leap years, 4 otherwise Mar 4 Apr 0 May 2 Jun 5 Jul 0 Aug 3 Sep 6 Oct 1 Nov 4 Dec 6
The day of the week formula is this. Let m, d, and y be the month, day and year of a given date, and let j be the "month adjustment" (per the table above) for the given month and year. Then let n be the following:
n = (y - 1900) + j + d + floor(y/4)where floor(y/4) is the integer quotient of y divided by 4. (For example, floor(401/4) is 100). Use the Typed Racket operation exact-floor in your code, or quotient if you prefer. Let w be the remainder of n divided by 7. Then if
Given this formula, now write
(: day-of-week (Date -> Day))
Explore the terminal command cal (man cal describes the command in detail). When you construct tests for this function, you can use cal to check your answers easily. You should test at least one day from every month of the year.
Every function must be preceded by a contract (type ascription) and a purpose and be followed by check tests. Remember to write (test) below your definitions to run all the tests.
Please submit one file, lab3.rkt, in a lab3 directory in your repository.