Assignment 3: Weekday Calculator (30 Points)
Chris Tralie
Due Monday 2/17/2020
Overview / Logistics
The purpose of this assignment is to get you practice with if statements
, modular arithmetic, methods
and testing with a fun application which will seem like magic once it works.
Click here to download the skeleton code for this assignment. You will be editing src/hw3_weekdaycalculator/HW3_WeekdayCalculator.java
and test/hw3_weekdaycalculator/HW3_WeekdayCalculatorTest.java
.
What to submit: When you are finished, you should submit these two files to Canvas. Please also submit answers to the following as a comment on Canvas:
 Did you work with a buddy on this assignment? If so, who?
 Are you using up any grace points to buy lateness days? If so, how many?
 Approximately how many hours it took you to finish this assignment (I will not judge you for this at all...I am simply using it to gauge if the assignments are too easy or hard)
 Your overall impression of the assignment. Did you love it, hate it, or were you neutral? One word answers are fine, but if you have any suggestions for the future let me know.
 Any other concerns that you have. For instance, if you have a bug that you were unable to solve but you made progress, write that here. The more you articulate the problem the more partial credit you will receive (fine to leave this blank)
The Problem
In lab 1, we saw that the orbit of the earth around the sun is slightly longer than 365 days (actually, more specifically, the tropical year is just under 365.25 days), so we wrote a program in lab 2 to compute years that are used as leap years in to keep our calendar days in the Gregorian Calendar on track with the summer solstice.
Now that we understand the calendar, we are ready to create a program that computes the weekday that any date falls on. The date may be any day in the past, present or future. To accomplish this, we will implement an algorithm invented by mathematician John Conway called the Doomsday Algorithm. This algorithm relies on the fact that there are a set of days every year (e.g. April 4th and June 6th) which always share the same weekday. These days are referred to as doomsdays. The weekday in question changes from year to year, though, so the challenge becomes to compute that day for a particular year, and then to find the nearest doomsday as a reference. We will refer to this day of the week as "the doomsday" for a particular year, and we will refer to one of the doomsdays as "a doomsday" (e.g. 4/4 and 6/6). For instance, in 2020, the doomsday is Saturday, so June 6 (a doomsday), 2020 is on a Saturday (we will discuss how to compute this day for any year momentarily). Therefore, if we want to know the date of June 4, 2020, we would count back by 2 to a Thursday.
Let's now look at the steps of the Doomsday Algorithm in more detail. In the discussion below, we will use numbers from 06 in the place of weekdays. In particular:
Weekdays as numbers
0  Sunday 
1  Monday 
2  Tuesday 
3  Wednesday 
4  Thursday 
5  Friday 
6  Saturday 
Your program will only need to return the number, but for extra credit you can use a switch statement on the number to print out the day.
1. Finding The Doomsday Weekday for A Particular Year
First, we need to figure out what day all of the doomsdays fall on for a particular year, which we refer to as that year's doomsday. These steps may seem like magic, and a proof is beyond the scope of this assignment, but if you follow them diligently, you will get perfectly correct answers.
Century Anchor
First, we need to find the "century anchor" for the doomsday. This is a number between 0 and 6 that we add as an offset when figuring out the weekday for the year. The century anchor is computed as follows:

Let
c
be the floor of of the year divided by 100. For example, for 1964, the century is 19 (you can get this with integer division, just as you got the number of buses on homework 1). 
Let
x
be(c % 4)*5

The
anchor
is then computed as(x % 7 + 2) % 7
Finalizing Doomsday Year
Now we are ready to finalize the doomsday. For this, we will use what's referred to as the "Odd + 11 method."" To carry it out, follow these steps in sequence:

Compute the
anchor
as above 
Let
T
be the 2digit year (the remainder when dividing the year by 100). For instance, for 1974,T
is 74. 
If
T
is odd, add 11 
Let
T
beT/2

If
T
is odd, add 11. 
Let
T
be7  T % 7

The doomsday for the year is
(T + anchor) % 7
2. Find The Weekday (Finally!!)
For a particular date, expressed as month/day/year
, we are now ready to find the day of the week of that date, expressed as a number. First, find the doomsday for the year
, following the steps above. Call this ydoomsday
. Then, given the month, find a known doomsday in that month, and count either forward or backward to it. In particular, the doomsdays for different months are shown in the table below. There are certainly more days than this that fall on the doomsday, but these ones were chosen so they would be easy to remember (e.g. 7/11 and 11/7, 9/5 and 5/9, 4/4, 6/6, 8/8, 10/10, 12/12)
January (1)  If it's a leap year, 1/4, otherwise, 1/3 
February (2)  If it's a leap year, 2/29, otherwise, 2/28 
March (3)  3/7 
April (4)  4/4 
May (5)  5/9 
June (6)  6/6 
July (7)  7/11 
August (8)  8/8 
September (9)  9/5 
October (10)  10/10 
November (11)  11/7 
December (12)  12/12 
ydoomsday
. For instance, notice how in 2020, all of these days fall on a Saturday, so ydoomsday = 6
. (Check your calendar...this will blow your mind). Call the particular day for a month reference
. For instance, reference = 5
for September (you will have to hard code in the references to a series of if statements or a switch statement on the month). Since we know that reference
occurs on ydoomsday
, we count back to reference
from our day
of the month. Do this by creating a variable diff = day  reference
Now add the year's doomsday offset
ydoomsday
to diff, and take the remainder after dividing by 7. If this remainder is negative, add 7. This is the final answer!!
Example 1
As an example, let's consider the day this assignment is due, 2/17/2020. As we discussed, the doomsday ydoomsday
for 2020 is 6 (we could get this by the steps above). We're on a leap year in February, so the day reference
is 29. Then, diff = 17  29 = 12
. So we're 12 days before a Saturday. In code, 12 % 7
is 5, which is negative, so we add 7 to it to get 2. By our number to weekday table, this is a Monday! So our assignment is due on Monday, as usual.
Example 2
Consider the attack on Pearl Harbor, which took place on December 7, 1941. First, we compute the century anchor:
 c = 19
 (19 % 4)*5 is 15
 (15 % 7 + 2) % 7 is 3
T = 41
 41 is odd, so set
T = 41 + 11 = 52
T = 52/2 = 26
26
is not odd, so leave it as isT = 7  26 % 7
, which is 2
ydoomsday
for the 1941 year is 3+2
ydoomsday or 5, a Friday. Next, we find the reference
for the month of December, which is 12
. The reference
12/12 of Friday is 5 days after our date of 12/7, so 12/7 must have been a Sunday. To see this following our procedure above, we computediff = 7  12 = 5
Since this is negative, we add 7 to it to get 2. Then, we add 2 + 5 (the doomsday for 1941) to get 7, which is 0 mod 7, which is a Sunday.
Programming Tasks (20 Points)
At a high level, your task is to compute the weekday of any date in the Gregorian calendar. To do this, you should fill in three methods HW3_WeekdayCalculator.java
. You should do them one at a time and test each method thoroughly before proceeding to the next. This is to get you to practice modular code development, in which you break a complex task down into lots of small little tasks, or modules, that match a specification. In this assignment, there is no hope that getDoomsdayYear
will work if getCenturyAnchor
isn't working, and there is no hope that getWeekday
will work if getCenturyAnchor
isn't working. More details are below:
1. getCenturyAnchor(int c)
(5 Points)
You are given the skeleton of a method whose job it is to compute a century anchor, given the digits of a century c
. You should return a number between 0 and 6 corresponding to this century's anchor.
2. getDoomsdayYear(int year)
(5 Points)
You should create a new method called getDoomsdayYear
which takes as input a year, and which returns a number between 0 and 6 corresponding to the doomsday for that year. A proper implementation of this method should call getCenturyAnchor
at some point to help with the calculation.
3. getWeekday(int year, int month, int day)
(10 Points)
You should create a new method called getWeekday
which takes as input the year, month (from 1 to 12), and day of a particular date, and which returns a number between 0 and 6 corresponding to the the number for the weekday of that day. A good implementation of this method should call getDoomsdayYear
at some point. You should also look up the doomsday corresponding to the current month with a series of if/else statements or with a switch statement. You should use your isALeapYear
function from lab 2 to check the special cases for January and February (feel free to copy and paste that function into this assignment).
Extra Credit (+2)
Create a method which takes as input a weekday as a number, and which returns a string corresponding to the actual day. Use this method to output the day as a word to the console.
Unit Tests (7 Points)
As always, testing is an important part of software development, and you will be graded on the quality of the tests you come up with. It is recommended that you create the tests as you are going along. You will need to create three sets of unit tests in the file tests/hw3_weekdaycalculator/HW3_WeekdayCalculatorTest.java
.

The first set is for
getCenturyAnchor
. You should add two centuries other than 1900 and 2000, which are provided. 
The next set of tests is for
getDoomsdayYear
. You will need to add at least 3 years in three different centuries in addition to 2020, which is already provided. Click here to see a bunch of examples of doomsdays for contemporary years. 
Finally, you will need to test the most important method of all,
getWeekday
. No test have been provided yet, but for the best coverage, you should add at least 12 tests spanning 12 different months. You can start with Peal Harbor day as your December test and the assignment due date as your February test. You may also want to add the day your were born, or some holiday some other year.
Style (3 Points)
You must adhere to the style guide as you are writing your code.