On this page:
1 Preparation
2 Year, Month and Day
3 calendar
4 days-between
5 time-passing
7.1

Assignment 3: Composing functions

This assignment is due on Wednesday, 1/23 at 11:59 PM. Submit it using the handin server as assignment a3.

Important Note: Whenever you design or write a function, you need to follow the design recipe, and you will be graded accordingly. In particular, every type mentioned in a signature must be introduced by a data definition, except for these well-known types: Number, Image, String, Boolean.

1 Preparation

In your textbook, turn to Chapter 2, Functions and Programs. Read Functions and Composing Functions.

You should also know how to use the design recipe with two kinds of data definitions, Enumerations and Intervals.

2 Year, Month and Day

You will design functions that use dates as conventionally written in English. The following data definitions will be used throughout the assignment, and more will be introduced as they are needed.

; A Year is a non-negative integer
; Examples:
;   0
;   1789
;   2018
; Non-examples:
;   -5000
;   "AD 2018"
 
; A Month is one of:
; - "January"
; - "February"
; - "March"
; - "April"
; - "May"
; - "June"
; - "July"
; - "August"
; - "September"
; - "October"
; - "November"
; - "December"
 
; A Day is an integer at least 1 but at most 31
; Examples:
;   1
;   10
;   31
; Non-examples:
;   32
;   "today"

Note that in general, it will be your job to create the data definitions. However, for this assignment we will provide the first steps of the design recipe, including the data definitions, so that you may focus on the subsequent steps in the design recipe.

Exercise 1 Finish designing the following function.
; next-month : Month -> Month
; returns the month that comes after the given one
(define (next-month m) ...)
 
(check-expect (next-month "September") "October")
(check-expect (next-month "December") "January")
Hint: your function template should make significant use of the Month data definition.

Exercise 2 Finish designing the following function.
; fall? : Month -> Boolean
; decides whether the given month is between September and November
Hint: your function template should make significant use of the Month data definition.

3 calendar

The goal of this section is to design a program that generates an image displaying a given date. This goal is summarized by the following signature and purpose statement:
; calendar : Year Month Day -> Image
; returns an image of a date on a background
To keep the calendar function simple to define and easy to improve, we design helper functions that will be used in it.

Because there are several ways to write the same date, we make two more data definitions to represent a choice of date format:
; A MonthFormat is one of:
; - "long"
; - "short"
 
; A DateOrder is one of:
; - "MDY"
; - "DMY"

Exercise 3 Finish designing the following function.
; format-month : Month MonthFormat -> String
; abbreviates Month to three letters or not
(define (format-month m f) ...)
 
(check-expect (format-month "November" "long") "November")
(check-expect (format-month "November" "short") "Nov")
Hint: your function template should make significant use of the MonthFormat data definition.

You will find the substring function useful here. Look it up in the documentation.

Exercise 4 Use format-month to design the following function:
; year-month-day->date : Year Month Day DateOrder MonthFormat -> String
; produces a date as a string
; given: 1936 "November" 12 "MDY" "long"   expect: "November 12, 1936"
; given: 1936 "November" 12 "MDY" "short"  expect: "Nov 12, 1936"
; given: 1936 "November" 12 "DMY" "long"   expect: "12 November 1936"
; given: 1936 "November" 12 "DMY" "short"  expect: "12 Nov 1936"
(define (year-month-day->date y m d o f) ...)
Hint: your function template should make significant use of the DateOrder data definition.

You will find the string-append function useful here. Look it up in the documentation.

For year-month-day->date and the other functions below, be sure to write unit tests with check-expect using the examples given (as well as any other examples you see fit to devise).

Exercise 5 Use year-month-day->date to design the calendar function, the goal of this section. You will need to choose one specific MonthFormat and one specific DateOrder that you like, as well as a background image to lay the text on. (If you are looking for some visual inspiration, do an image search online for the painter On Kawara.)

4 days-between

The goal of this section is to design a program that calculates the number of days between two dates. As above, we decompose this task into subtasks to be carried out by helper functions.

To simplify, we pretend that every year has 365 days.

Analyzing this problem, we settle on the following approach. Given a date, we calculate how many days have elapsed since the earliest possible date (according to our definitions above): 1 Jan, 0. Let’s call this function year-month-day->days.
; year-month-day->days : Year Month Day -> Number
; returns the number of days elapsed since January 1, 0
; given: 0 "January" 1     expect: 0
; given: 2017 "August" 28  expect: 736444
Notice that year-month-day->days itself is not completely straightforward, because month lengths vary. Let us then tackle first the number of days before a given month.

Exercise 6 Finish designing the following function.
; month->days-in-year : Month -> Number
; returns the days elapsed in the year before the given month
; given: "January"    expect: 0
; given: "September"  expect: 243
Hint: your function template should make significant use of the Month data definition.

Exercise 7 Finish designing year-month-day->days. Use month->days-in-year in the definition.

Exercise 8 Design the function days-between, the goal of this section. This function should take two dates as input and calculate the number of days between them. Here is the signature:
; days-between : Year Month Day Year Month Day -> Number
Be sure to complete the purpose statement and devise examples/tests for days-between. With year-month-day->days in hand, the definition of days-between is a matter of basic arithmetic. Because days-between should return a non-negative integer, consider using the abs function.

5 time-passing

In this section, the goal is to design a program which produces a simple animation of calendar. The animation will show the days of this semester passing, using animate.

Take a moment to reflect on this problem and where the difficulty lies. In a sense, we would like to feed calendar to animate, relax and watch the show. However, calendar takes three inputs, not a single number of days.

So we cannot simply compose animate and calendar. But we can design functions which allow us to connect the two. We need to turn a number of days into a Year, into a Month, and into a Day.

Exercise 9 To start with, design the function days->year:
; days->year : Number -> Year
; takes days since 1 Jan 0 and returns the year
; given: 364                                       expect: 0
; given: 365                                       expect: 1
; given: 736305                                    expect: 2017
; given: (year-month-day->days 1999 "December" 31) expect: 1999
The last example illustrates that days->year should be sort of an inverse to year-month-day->days.

Notice that days->year can be used to supply the Year to calendar. We also want days->month and days->day to supply the Month and Day to calendar. But these two functions are more challenging, because month lengths vary. So we provide the following data definitions, which are intervals:
; DaysInYear is one of:
; - an integer at least   0 but less than  31
; - an integer at least  31 but less than  59
; - an integer at least  59 but less than  90
; - an integer at least  90 but less than 120
; - an integer at least 120 but less than 151
; - an integer at least 151 but less than 181
; - an integer at least 181 but less than 212
; - an integer at least 212 but less than 243
; - an integer at least 243 but less than 273
; - an integer at least 273 but less than 304
; - an integer at least 304 but less than 334
; - an integer at least 334 but less than 365
; *Interpretation*: the number of elapsed days
;                   since the first day of the year
 
; DaysInMonth is an integer at least 0 but less than 31
; *Interpretation*: The number of elapsed days
;                   since the first day of the month

Both days->month and days->day should be defined using helpers.

Exercise 10 Design the function days->month, by first designing the helper function days-in-year->month:
; days-in-year->month : DaysInYear -> Month
; takes days since the first of the year and returns the month
; given: 0    expect: "January"
; given: 31   expect: "February"
; given: 242  expect: "August"
 
; days->month : Number -> Month
; takes days since 1 Jan 0 and returns the month
; given: 59                                        expect: "March"
; given: 364                                       expect: "December"
; given: 736445                                    expect: "August"
; given: (year-month-day->days 1999 "December" 31) expect: "December"
Hint: Be sure that your template for days-in-year->month makes use of the DaysInYear data definition.

Exercise 11 Design the function days->day, by first designing the helper function days-in-year->days-in-month:
; days-in-year->days-in-month : DaysInYear -> DaysInMonth
; takes days since the first of the year
; and returns days since the first of the month
; given: 0       expect: 0
; given: 59      expect: 0
; given: 364     expect: 30
 
; days->day : Number -> Day
; takes days since 1 Jan 0 and returns the day of the month
; given: 0                                         expect: 1
; given: 59                                        expect: 1
; given: 736324                                    expect: 30
; given: (year-month-day->days 1999 "December" 31) expect: 31
Hint: To define days-in-year->days-in-month, even though the input DaysInYear is an enumeration, it is not necessary to use cond. Instead, compose the existing functions days-in-year->month and month->days-in-year.

Finally, we are ready to build our animation.

Exercise 12 Let’s create an animation which shows the days of this semester passing. The first day of this semester was January 7. The last day will be May 3.

Finish designing spring-2019-cal.

; first-day : Number
; The number of days elapsed on January 7, 2019 since January 1, 0
(define first-day ...)
 
; length-of-semester : Number
; The number of days elapsed on May 3, 2019 since January 7, 2019
(define length-of-semester ...)
 
; a Spring2019Day is one of:
; - an integer n, 0 <= n < length-of-semester
;   *Interpretation*: n days have elapsed since January 7, 2019
; - an integer n, n >= length-of-semester
;   *Interpretation*: The semester has ended
 
; spring-2019-cal : Spring2019Day -> Image
; takes a number of days since the first day of the semester
; and returns a calendar image of the corresponding date; does
; not advance past the last day of the semester
(define (spring-2019-cal t) ...)

If you pass spring-2019-cal to animate, you should see an animation that starts on January 7, 2019, passes through the days quickly, and stops on May 3, 2019.

The calendar pages in this animation pass rather quickly: 28 per second to be exact. Let’s slow it down. Pick how many calendar pages per second you would like to see and define this number as cal-rate. You can then convert an animation tick number to a Spring2019Day, by multiplying by cal-rate and then quotienting by 28.

Design a function spring-2019 which takes a tick number, converts it to a Spring2019Day and passes the result to spring-2019-cal to produce an image.

Your final program should produce a running animation using spring-2019.

Challenge Let’s add some information to our Spring semester calendar. Days when C211/H211 meet should display differently (e.g., by a different color text or background) than other days. Also, holidays (Saturdays, Sundays, MLK Jr Day, spring break) should display differently than non-holidays. Refine the data definition of Spring2019Day and the functions that depend on it to give you an animated calendar which alerts you to class days and holidays.

Feel free to customize your calendar further.