Difference between revisions of "Calendar Date Assignment"
(31 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
− | + | =Hints and Gotchas= | |
+ | [https://www.coursera.org/learn/programming-languages/supplement/MHfZa/hints-and-gotchas-for-homework-1 Hints and Gotchas] credit to [https://vault.hanover.edu/~skiadas/ Charilaos Skiadas] | ||
− | [https://www.coursera.org/learn/programming-languages/ | + | =Credit= |
+ | {{GrossmanCredit}} | ||
+ | |||
+ | [https://courses.cs.washington.edu/courses/cse341/13sp/hw1.pdf UW] or [https://www.coursera.org/learn/programming-languages/programming/ZTeNx/homework-1-instructions Coursera] | ||
+ | |||
+ | =Code to Implement= | ||
+ | You will write 11 SML functions (and tests for them) related to calendar dates. In all problems, a “date” | ||
+ | is an SML value of type <code>int*int*int</code>, where the first part is the year, the second part is the month, and | ||
+ | the third part is the day. A “reasonable” date has a positive year, a month between 1 and 12, and a day no | ||
+ | greater than 31 (or less depending on the month). Your solutions need to work correctly only for reasonable | ||
+ | dates, but do not check for reasonable dates (that is a challenge problem) and many of your functions will | ||
+ | naturally work correctly for some/all non-reasonable dates. A “day of year” is a number from 1 to 365 | ||
+ | where, for example, 33 represents February 2. (We ignore leap years except in one challenge problem.) | ||
+ | |||
+ | {{SMLToImplement|uw1|is_older<br/>number_in_month<br/>number_in_months<br/>dates_in_month<br/>dates_in_months<br/>get_nth<br/>date_to_string<br/>number_before_reaching_sum<br/>what_month<br/>month_range<br/>oldest<br/>number_in_months_challenge<br/>dates_in_months_challenge<br/>reasonable_date|uw1}} | ||
+ | |||
+ | ==1) is_older== | ||
+ | Write a function <code>is_older</code> that takes two dates and evaluates to true or false. It evaluates to true if | ||
+ | the first argument is a date that comes before the second argument. (If the two dates are the same, | ||
+ | the result is false.) | ||
+ | ==2) number_in_month== | ||
+ | Write a function <code>number_in_month</code> that takes a list of dates and a month (i.e., an <code>int</code>) and returns | ||
+ | how many dates in the list are in the given month. | ||
+ | ==3) number_in_months== | ||
+ | Write a function <code>number_in_months</code> that takes a list of dates and a list of months (i.e., an <code>int list</code>) | ||
+ | and returns the number of dates in the list of dates that are in any of the months in the list of months. | ||
+ | ''Assume the list of months has no number repeated.'' Hint: Use your answer to the previous problem. | ||
+ | ==4) dates_in_month== | ||
+ | Write a function <code>dates_in_month</code> that takes a list of dates and a month (i.e., an <code>int</code>) and returns a | ||
+ | list holding the dates from the argument list of dates that are in the month. The returned list should | ||
+ | contain dates in the order they were originally given. | ||
+ | ==5) dates_in_months== | ||
+ | Write a function <code>dates_in_months</code> that takes a list of dates and a list of months (i.e., an <code>int list</code>) | ||
+ | and returns a list holding the dates from the argument list of dates that are in any of the months in | ||
+ | the list of months. ''Assume the list of months has no number repeated.'' Hint: Use your answer to the | ||
+ | previous problem and SML’s list-append operator ([https://smlfamily.github.io/Basis/list.html#SIG:LIST.@:VAL @]). | ||
+ | ==6) get_nth== | ||
+ | Write a function <code>get_nth</code> that takes a list of strings and an <code>int</code> n and returns the nth element of the | ||
+ | list where the head of the list is 1st. Do not worry about the case where the list has too few elements: | ||
+ | your function may apply <code>hd</code> or <code>tl</code> to the empty list in this case, which is okay. | ||
+ | ==7) date_to_string== | ||
+ | Write a function <code>date_to_string</code> that takes a date and returns a string of the form January 20, 2013 | ||
+ | (for example). Use the operator <code>^</code> for concatenating strings and the library function <code>Int.toString</code> | ||
+ | for converting an <code>int</code> to a <code>string</code>. For producing the month part, do ''not'' use a bunch of conditionals. | ||
+ | Instead, use a list holding 12 strings and your answer to the previous problem. For consistency, put a | ||
+ | comma following the day and use capitalized English month names: January, February, March, April, | ||
+ | May, June, July, August, September, October, November, December. | ||
+ | ==8) number_before_reaching_sum== | ||
+ | Write a function <code>number_before_reaching_sum</code> that takes an <code>int</code> called ''sum'', which you can assume | ||
+ | is positive, and an <code>int list</code>, which you can assume contains all positive numbers, and returns an <code>int</code>. | ||
+ | You should return an int ''n'' such that the first ''n'' elements of the list add to less than sum, but the first | ||
+ | ''n + 1'' elements of the list add to ''sum'' or more. Assume the entire list sums to more than the passed in | ||
+ | value; it is okay for an exception to occur if this is not the case. | ||
+ | ==9) what_month== | ||
+ | Write a function <code>what_month</code> that takes a day of year (i.e., an int between 1 and 365) and returns | ||
+ | what month that day is in (1 for January, 2 for February, etc.). Use a list holding 12 integers and your | ||
+ | answer to the previous problem. | ||
+ | ==10) month_range== | ||
+ | Write a function <code>month_range</code> that takes two days of the year day1 and day2 and returns an <code>int list | ||
+ | [m1,m2,...,mn]</code> where m1 is the month of day1, m2 is the month of day1+1, ..., and mn is the month | ||
+ | of day day2. Note the result will have length day2 - day1 + 1 or length 0 if day1>day2. | ||
+ | ==11) oldest== | ||
+ | Write a function <code>oldest</code> that takes a list of dates and evaluates to an <code>(int*int*int) option</code>. It | ||
+ | evaluates to <code>NONE</code> if the list has no dates and <code>SOME d</code> if the date d is the oldest date in the list. | ||
+ | ==12) number_in_months_challenge, and dates_in_months_challenge== | ||
+ | Challenge Problem: Write functions <code>number_in_months_challenge</code> and <code>dates_in_months_challenge</code> | ||
+ | that are like your solutions to problems 3 and 5 except having a month in the second argument multiple | ||
+ | times has no more effect than having it once. (Hint: remove duplicates, then use previous work.) | ||
+ | |||
+ | ==13) reasonable_date== | ||
+ | Challenge Problem: Write a function <code>reasonable_date</code> that takes a date and determines if it | ||
+ | describes a real date in the common era. A “real date” has a positive year (year 0 did not exist), a | ||
+ | month between 1 and 12, and a day appropriate for the month. Solutions should properly handle leap | ||
+ | years. Leap years are years that are either divisible by 400 or divisible by 4 but not divisible by 100. | ||
+ | (Do not worry about days possibly lost in the conversion to the Gregorian calendar in the Late 1500s.) | ||
+ | <!--Note: Remember challenge problems are not required for a high grade and will be worth (only) a few points. | ||
+ | |||
+ | Note: The sample solution contains roughly 75–80 lines of code, not including challenge problems.--> | ||
+ | |||
+ | =Syntax Hints= | ||
+ | Small syntax errors can lead to strange error messages. Here are 3 examples for function definitions: | ||
+ | # <code>int * int * int list</code> means <code>int * int * (int list)</code>, not <code>(int * int * int) list</code>. | ||
+ | # <code>fun f x : t</code> means the ''result type'' of f is t, whereas fun f (x:t) means the argument type of f is t. There is no need to write result types (and in later assignments, no need to write argument types). | ||
+ | # <code>fun (x t)</code>, <code>fun (t x)</code>, or <code>fun (t : x)</code> are all wrong, but the error message suggests you are trying to do something much more advanced than you actually are (which is trying to write <code>fun (x : t)</code>). | ||
+ | |||
+ | =Summary= | ||
+ | Evaluating a correct homework solution should generate these bindings: | ||
+ | <syntaxhighlight lang="sml"> | ||
+ | val is_older = fn : (int * int * int) * (int * int * int) -> bool | ||
+ | val number_in_month = fn : (int * int * int) list * int -> int | ||
+ | val number_in_months = fn : (int * int * int) list * int list -> int | ||
+ | val dates_in_month = fn : (int * int * int) list * int -> (int * int * int) list | ||
+ | val dates_in_months = fn : (int * int * int) list * int list -> (int * int * int) list | ||
+ | val get_nth = fn : string list * int -> string | ||
+ | val date_to_string = fn : int * int * int -> string | ||
+ | val number_before_reaching_sum = fn : int * int list -> int | ||
+ | val what_month = fn : int -> int | ||
+ | val month_range = fn : int * int -> int list | ||
+ | val oldest = fn : (int * int * int) list -> (int * int * int) option | ||
+ | val number_in_months_challenge = fn : (int * int * int) list * int list -> int | ||
+ | val dates_in_months_challenge = fn : (int * int * int) list * int list -> (int * int * int) list | ||
+ | val reasonable_date = fn : int * int * int -> bool | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Of course, generating these bindings does not guarantee that your solutions are correct. | ||
+ | |||
+ | =Test= | ||
+ | {{SMLUnitTesting|run_uw1_testing|uw1}} | ||
+ | |||
+ | Test your functions. The unit tests you have been provided from UW are intentionally minimal. | ||
+ | |||
+ | =Pledge, Acknowledgments, Citations= | ||
+ | {{Pledge|uw1-calendar-date}} |
Latest revision as of 18:46, 10 July 2023
Contents
- 1 Hints and Gotchas
- 2 Credit
- 3 Code to Implement
- 3.1 1) is_older
- 3.2 2) number_in_month
- 3.3 3) number_in_months
- 3.4 4) dates_in_month
- 3.5 5) dates_in_months
- 3.6 6) get_nth
- 3.7 7) date_to_string
- 3.8 8) number_before_reaching_sum
- 3.9 9) what_month
- 3.10 10) month_range
- 3.11 11) oldest
- 3.12 12) number_in_months_challenge, and dates_in_months_challenge
- 3.13 13) reasonable_date
- 4 Syntax Hints
- 5 Summary
- 6 Test
- 7 Pledge, Acknowledgments, Citations
Hints and Gotchas
Hints and Gotchas credit to Charilaos Skiadas
Credit
All credit for this assignment goes to Prof. Grossman and his team at UW.
Code to Implement
You will write 11 SML functions (and tests for them) related to calendar dates. In all problems, a “date”
is an SML value of type int*int*int
, where the first part is the year, the second part is the month, and
the third part is the day. A “reasonable” date has a positive year, a month between 1 and 12, and a day no
greater than 31 (or less depending on the month). Your solutions need to work correctly only for reasonable
dates, but do not check for reasonable dates (that is a challenge problem) and many of your functions will
naturally work correctly for some/all non-reasonable dates. A “day of year” is a number from 1 to 365
where, for example, 33 represents February 2. (We ignore leap years except in one challenge problem.)
1) is_older
Write a function is_older
that takes two dates and evaluates to true or false. It evaluates to true if
the first argument is a date that comes before the second argument. (If the two dates are the same,
the result is false.)
2) number_in_month
Write a function number_in_month
that takes a list of dates and a month (i.e., an int
) and returns
how many dates in the list are in the given month.
3) number_in_months
Write a function number_in_months
that takes a list of dates and a list of months (i.e., an int list
)
and returns the number of dates in the list of dates that are in any of the months in the list of months.
Assume the list of months has no number repeated. Hint: Use your answer to the previous problem.
4) dates_in_month
Write a function dates_in_month
that takes a list of dates and a month (i.e., an int
) and returns a
list holding the dates from the argument list of dates that are in the month. The returned list should
contain dates in the order they were originally given.
5) dates_in_months
Write a function dates_in_months
that takes a list of dates and a list of months (i.e., an int list
)
and returns a list holding the dates from the argument list of dates that are in any of the months in
the list of months. Assume the list of months has no number repeated. Hint: Use your answer to the
previous problem and SML’s list-append operator (@).
6) get_nth
Write a function get_nth
that takes a list of strings and an int
n and returns the nth element of the
list where the head of the list is 1st. Do not worry about the case where the list has too few elements:
your function may apply hd
or tl
to the empty list in this case, which is okay.
7) date_to_string
Write a function date_to_string
that takes a date and returns a string of the form January 20, 2013
(for example). Use the operator ^
for concatenating strings and the library function Int.toString
for converting an int
to a string
. For producing the month part, do not use a bunch of conditionals.
Instead, use a list holding 12 strings and your answer to the previous problem. For consistency, put a
comma following the day and use capitalized English month names: January, February, March, April,
May, June, July, August, September, October, November, December.
8) number_before_reaching_sum
Write a function number_before_reaching_sum
that takes an int
called sum, which you can assume
is positive, and an int list
, which you can assume contains all positive numbers, and returns an int
.
You should return an int n such that the first n elements of the list add to less than sum, but the first
n + 1 elements of the list add to sum or more. Assume the entire list sums to more than the passed in
value; it is okay for an exception to occur if this is not the case.
9) what_month
Write a function what_month
that takes a day of year (i.e., an int between 1 and 365) and returns
what month that day is in (1 for January, 2 for February, etc.). Use a list holding 12 integers and your
answer to the previous problem.
10) month_range
Write a function month_range
that takes two days of the year day1 and day2 and returns an int list
[m1,m2,...,mn]
where m1 is the month of day1, m2 is the month of day1+1, ..., and mn is the month
of day day2. Note the result will have length day2 - day1 + 1 or length 0 if day1>day2.
11) oldest
Write a function oldest
that takes a list of dates and evaluates to an (int*int*int) option
. It
evaluates to NONE
if the list has no dates and SOME d
if the date d is the oldest date in the list.
12) number_in_months_challenge, and dates_in_months_challenge
Challenge Problem: Write functions number_in_months_challenge
and dates_in_months_challenge
that are like your solutions to problems 3 and 5 except having a month in the second argument multiple
times has no more effect than having it once. (Hint: remove duplicates, then use previous work.)
13) reasonable_date
Challenge Problem: Write a function reasonable_date
that takes a date and determines if it
describes a real date in the common era. A “real date” has a positive year (year 0 did not exist), a
month between 1 and 12, and a day appropriate for the month. Solutions should properly handle leap
years. Leap years are years that are either divisible by 400 or divisible by 4 but not divisible by 100.
(Do not worry about days possibly lost in the conversion to the Gregorian calendar in the Late 1500s.)
Syntax Hints
Small syntax errors can lead to strange error messages. Here are 3 examples for function definitions:
int * int * int list
meansint * int * (int list)
, not(int * int * int) list
.fun f x : t
means the result type of f is t, whereas fun f (x:t) means the argument type of f is t. There is no need to write result types (and in later assignments, no need to write argument types).fun (x t)
,fun (t x)
, orfun (t : x)
are all wrong, but the error message suggests you are trying to do something much more advanced than you actually are (which is trying to writefun (x : t)
).
Summary
Evaluating a correct homework solution should generate these bindings:
val is_older = fn : (int * int * int) * (int * int * int) -> bool
val number_in_month = fn : (int * int * int) list * int -> int
val number_in_months = fn : (int * int * int) list * int list -> int
val dates_in_month = fn : (int * int * int) list * int -> (int * int * int) list
val dates_in_months = fn : (int * int * int) list * int list -> (int * int * int) list
val get_nth = fn : string list * int -> string
val date_to_string = fn : int * int * int -> string
val number_before_reaching_sum = fn : int * int list -> int
val what_month = fn : int -> int
val month_range = fn : int * int -> int list
val oldest = fn : (int * int * int) list -> (int * int * int) option
val number_in_months_challenge = fn : (int * int * int) list * int list -> int
val dates_in_months_challenge = fn : (int * int * int) list * int list -> (int * int * int) list
val reasonable_date = fn : int * int * int -> bool
Of course, generating these bindings does not guarantee that your solutions are correct.
Test
source folder: | src/test/sml/uw1 |
how to run with CM.make verbosity off: | sml -Ccm.verbose=false run_uw1_testing.sml |
how to run with CM.make verbosity on: | sml run_uw1_testing.sml |
note: ensure that you have removed all printing to receive credit for any assignment.
Test your functions. The unit tests you have been provided from UW are intentionally minimal.
Pledge, Acknowledgments, Citations
file: | uw1-calendar-date-pledge-acknowledgments-citations.txt |
More info about the Honor Pledge