/*
* doomsday.c
* A program to test a function dayOfWeek which determines which
* day of the week a particular date falls on.
* (only for dates after the start of the Gregorian calendar).
*
* Program stub created by Richard Buckland on 17/03/14
* This program by Sabrina Rispin
* Freely licensed under Creative Commons CC-BY-3.0
*
*
*/
//---------------------------72-characters------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define THURSDAY 0
#define FRIDAY 1
#define SATURDAY 2
#define SUNDAY 3
#define MONDAY 4
#define TUESDAY 5
#define WEDNESDAY 6
#define TRUE 1
#define FALSE 0
#define DAYS_PER_WEEK 7
int dayOfWeek (int doomsday, int leapYear, int month, int day);
void checkValidInput (int doomsday, int leapYear, int month, int day);
int findCloseDoomDay (int doomsday, int leapYear, int month, int day);
void testPrint (int testGroup);
void runUnitTests (void);
void testConstants (void);
int main (int argc, char * argv[]) {
runUnitTests();
testConstants();
printf ("all tests passed - You are awesome!\n");
return EXIT_SUCCESS;
}
// given the doomsday for a year, and whether or not it is a
// leap year, this function return the day of the week for any
// given month and day in the year.
int dayOfWeek (int doomsday, int leapYear, int month, int day) {
int dayOfWeek;
int closeDoomDay;
checkValidInput (doomsday, leapYear, month, day);
closeDoomDay = findCloseDoomDay (doomsday, leapYear, month, day);
// Make dayOfWeek a day in the first week of that month
// and do the same to the closeDoomDay
day = day % DAYS_PER_WEEK;
closeDoomDay = closeDoomDay % DAYS_PER_WEEK;
// The day - closeDoomDay will show how many days off
// the day is from a doomsday day
// dayOfWeek = day of the doomsday day - the diff
dayOfWeek = doomsday + (day - closeDoomDay);
if (dayOfWeek < 0) {
// e.g. if the dayOfWeek = -1 (which should be 6)
dayOfWeek = dayOfWeek + DAYS_PER_WEEK;
} else if (dayOfWeek > (DAYS_PER_WEEK - 1)) {
// e.g. if the dayOfWeek = 10 (which should be 3)
dayOfWeek = dayOfWeek % DAYS_PER_WEEK;
}
// Optional print statements: used to manually work out the ans
// Useful if assert failure happens
/*
printf ("doomsday: %d\n", doomsday);
printf ("closeDoomDay: %d\n", closeDoomDay);
printf ("day: %d\n", day);
printf ("difference: %d\n", (day - closeDoomDay));
printf ("dayOfWeek: %d\n\n", dayOfWeek);
*/
return (dayOfWeek);
}
void checkValidInput (int doomsday, int leapYear, int month, int day) {
// Check for valid inputs
assert (doomsday >= THURSDAY && doomsday <= WEDNESDAY);
assert (leapYear == TRUE || leapYear == FALSE);
assert (month >= 1 && month <= 12);
assert (day >= 1 && day <= 31);
if (day == 31) {
assert (month == 1 || 3 || 5 || 7 || 8 || 10 || 12);
}
if (month == 2) {
if (leapYear) {
assert (day >= 1 && day <= 29);
} else {
assert (day >= 1 && day <= 28);
}
}
}
int findCloseDoomDay (int doomsday, int leapYear, int month, int day) {
int closeDoomDay;
// find a doomsday day in each month
if (month >= 1 && month <= 3) {
// closest days that falls on the doomsday for Jan, Feb and March
if (month == 1) {
// Jan
closeDoomDay = 3;
} else {
// Feb and Mar - same day for both
closeDoomDay = 0;
}
// check for leap years (Jan and Feb)
if (leapYear && month != 3) {
closeDoomDay++;
}
} else if ((month % 2) == 0) {
// The 4/4, 6/6, 8/8, 10/10, 12/12 rule
closeDoomDay = month;
} else {
// The 5/9, 7/11, 9/5, 11/7 rule
if (month == 5) {
closeDoomDay = 9;
} else if (month == 7) {
closeDoomDay = 11;
} else if (month == 9) {
closeDoomDay = 5;
} else {
closeDoomDay = 7;
}
}
return (closeDoomDay);
}
void testPrint (int testGroup) {
printf("Group %d has passed - You are awesome!\n\n",testGroup);
}
void testConstants (void) {
// Are the days their assumed values
assert(THURSDAY == 0);
assert(FRIDAY == 1);
assert(SATURDAY == 2);
assert(SUNDAY == 3);
assert(MONDAY == 4);
assert(TUESDAY == 5);
assert(WEDNESDAY == 6);
// DAYS_PER_WEEK is the number of days above
assert(DAYS_PER_WEEK == 7);
// Basic logic check for TRUE FALSE
assert(TRUE != FALSE);
printf("\nAll constants are correctly defined.\n");
}
void runUnitTests (void) {
int testNumber = 0;
printf ("Testing group 1: Doomsday's\n");
assert (dayOfWeek (THURSDAY, FALSE, 4, 4) == THURSDAY);
assert (dayOfWeek (FRIDAY, FALSE, 6, 6) == FRIDAY);
assert (dayOfWeek (MONDAY, FALSE, 8, 8) == MONDAY);
assert (dayOfWeek (WEDNESDAY, FALSE, 10, 10) == WEDNESDAY);
assert (dayOfWeek (FRIDAY, FALSE, 12, 12) == FRIDAY);
assert (dayOfWeek (THURSDAY, FALSE, 9, 5) == THURSDAY);
assert (dayOfWeek (FRIDAY, FALSE, 5, 9) == FRIDAY);
assert (dayOfWeek (SUNDAY, FALSE, 7, 11) == SUNDAY);
assert (dayOfWeek (TUESDAY, FALSE, 11, 7) == TUESDAY);
assert (dayOfWeek (WEDNESDAY, FALSE, 3, 7) == WEDNESDAY);
testNumber++;
testPrint (testNumber);
//JANUARY leap year testing
printf ("Testing January Leap Year\n");
assert (dayOfWeek (MONDAY, FALSE, 1, 1) == SATURDAY);
assert (dayOfWeek (MONDAY, FALSE, 1, 29) == SATURDAY);
assert (dayOfWeek (MONDAY, FALSE, 1, 31) == MONDAY);
assert (dayOfWeek (WEDNESDAY, TRUE, 1, 1) == SUNDAY);
assert (dayOfWeek (WEDNESDAY, TRUE, 1, 29) == SUNDAY);
assert (dayOfWeek (WEDNESDAY, TRUE, 1, 31) == TUESDAY);
testNumber++;
testPrint (testNumber);
//FEBRUARY leap year testing
printf ("Testing February Leap Year\n");
assert (dayOfWeek (MONDAY, FALSE, 2, 1) == TUESDAY);
assert (dayOfWeek (MONDAY, FALSE, 2, 28) == MONDAY);
assert (dayOfWeek (TUESDAY, TRUE, 2, 1) == TUESDAY);
assert (dayOfWeek (TUESDAY, TRUE, 2, 28) == MONDAY);
assert (dayOfWeek (TUESDAY, TRUE, 2, 29) == TUESDAY);
testNumber++;
testPrint (testNumber);
// Test cases further than one week behind doomsday
printf ("Testing > 1 week before Doomsday\n");
assert (dayOfWeek (SATURDAY, FALSE, 12, 1) == TUESDAY);
assert (dayOfWeek (SATURDAY, FALSE, 10, 1) == THURSDAY);
testNumber++;
testPrint (testNumber);
// Test one week ahead
printf ("Testing > 1 week after Doomsday\n");
assert (dayOfWeek (FRIDAY, FALSE, 6, 30) == MONDAY);
assert (dayOfWeek (FRIDAY, FALSE, 6, 13) == FRIDAY);
testNumber++;
testPrint (testNumber);
// First day of each month
printf ("Testing first day of each month\n");
assert (dayOfWeek (MONDAY, FALSE, 1, 1) == SATURDAY);
assert (dayOfWeek (MONDAY, FALSE, 2, 1) == TUESDAY);
assert (dayOfWeek (MONDAY, FALSE, 3, 1) == TUESDAY);
assert (dayOfWeek (MONDAY, FALSE, 4, 1) == FRIDAY);
assert (dayOfWeek (MONDAY, FALSE, 5, 1) == SUNDAY);
assert (dayOfWeek (MONDAY, FALSE, 6, 1) == WEDNESDAY);
assert (dayOfWeek (MONDAY, FALSE, 7, 1) == FRIDAY);
assert (dayOfWeek (MONDAY, FALSE, 8, 1) == MONDAY);
assert (dayOfWeek (MONDAY, FALSE, 9, 1) == THURSDAY);
assert (dayOfWeek (MONDAY, FALSE, 10, 1) == SATURDAY);
assert (dayOfWeek (MONDAY, FALSE, 11, 1) == TUESDAY);
assert (dayOfWeek (MONDAY, FALSE, 12, 1) == THURSDAY);
assert (dayOfWeek (MONDAY, TRUE, 1, 1) == FRIDAY);
assert (dayOfWeek (MONDAY, TRUE, 2, 1) == MONDAY);
testNumber++;
testPrint (testNumber);
// Last day of each month
printf ("Testing last day of each month\n");
assert (dayOfWeek (MONDAY, FALSE, 1, 31) == MONDAY);
assert (dayOfWeek (MONDAY, FALSE, 2, 28) == MONDAY);
assert (dayOfWeek (MONDAY, FALSE, 3, 31) == THURSDAY);
assert (dayOfWeek (MONDAY, FALSE, 4, 30) == SATURDAY);
assert (dayOfWeek (MONDAY, FALSE, 5, 31) == TUESDAY);
assert (dayOfWeek (MONDAY, FALSE, 6, 30) == THURSDAY);
assert (dayOfWeek (MONDAY, FALSE, 7, 31) == SUNDAY);
assert (dayOfWeek (MONDAY, FALSE, 8, 31) == WEDNESDAY);
assert (dayOfWeek (MONDAY, FALSE, 9, 30) == FRIDAY);
assert (dayOfWeek (MONDAY, FALSE, 10, 31) == MONDAY);
assert (dayOfWeek (MONDAY, FALSE, 11, 30) == WEDNESDAY);
assert (dayOfWeek (MONDAY, FALSE, 12, 31) == SATURDAY);
assert (dayOfWeek (MONDAY, TRUE, 1, 31) == SUNDAY);
assert (dayOfWeek (MONDAY, TRUE, 2, 29) == MONDAY);
testNumber++;
testPrint (testNumber);
//One day before doomsday
printf ("Testing one day before doomsday of each relevant month\n");
assert (dayOfWeek (THURSDAY, TRUE, 2, 28) == WEDNESDAY);
assert (dayOfWeek (THURSDAY, FALSE, 2, 27) == WEDNESDAY);
assert (dayOfWeek (THURSDAY, FALSE, 4, 3) == WEDNESDAY);
assert (dayOfWeek (THURSDAY, FALSE, 5, 8) == WEDNESDAY);
assert (dayOfWeek (THURSDAY, FALSE, 6, 5) == WEDNESDAY);
assert (dayOfWeek (THURSDAY, FALSE, 7, 10) == WEDNESDAY);
assert (dayOfWeek (THURSDAY, FALSE, 8, 7) == WEDNESDAY);
assert (dayOfWeek (THURSDAY, FALSE, 9, 4) == WEDNESDAY);
assert (dayOfWeek (THURSDAY, FALSE, 10, 9) == WEDNESDAY);
assert (dayOfWeek (THURSDAY, FALSE, 11, 6) == WEDNESDAY);
assert (dayOfWeek (THURSDAY, FALSE, 12, 11) == WEDNESDAY);
testNumber++;
testPrint (testNumber);
//just a test
printf ("Just a test.\n");
assert (dayOfWeek (FRIDAY, FALSE, 11, 9) == SUNDAY);
testNumber++;
testPrint (testNumber);
//Test Christmas Day and Boxing Day
printf ("Test Christmas Day and Boxing Day\n");
assert (dayOfWeek (SATURDAY, FALSE, 12, 25) == FRIDAY);
assert (dayOfWeek (SATURDAY, FALSE, 12, 26) == SATURDAY);
testNumber++;
testPrint (testNumber);
// Test Pi Day
printf ("Test Pi Day\n");
assert (dayOfWeek (TUESDAY, FALSE, 3, 14) == TUESDAY);
testNumber++;
testPrint (testNumber);
//Group 11: Test for Unexpected Inputs
printf ("Testing group 11: Test for Unexpected Inputs\n");
assert (dayOfWeek (THURSDAY, FALSE, -1, 31) != MONDAY || TUESDAY ||
WEDNESDAY || THURSDAY || FRIDAY || SATURDAY || SUNDAY);
assert (dayOfWeek (THURSDAY, FALSE, 1, 31) != MONDAY || TUESDAY ||
WEDNESDAY || THURSDAY || FRIDAY || SATURDAY || SUNDAY);
assert (dayOfWeek (THURSDAY, FALSE, 2, 29) != MONDAY || TUESDAY ||
WEDNESDAY || THURSDAY || FRIDAY || SATURDAY || SUNDAY);
assert (dayOfWeek (THURSDAY, FALSE, 13, 46) != MONDAY || TUESDAY || WEDNESDAY || THURSDAY || FRIDAY || SATURDAY || SUNDAY);
assert (dayOfWeek (7, FALSE, 2, 4) != MONDAY || TUESDAY ||
WEDNESDAY || THURSDAY || FRIDAY || SATURDAY || SUNDAY);
assert (dayOfWeek (8, FALSE, 2, 4) != MONDAY || TUESDAY ||
WEDNESDAY || THURSDAY || FRIDAY || SATURDAY || SUNDAY);
assert (dayOfWeek (9, FALSE, 2, 4) != MONDAY || TUESDAY ||
WEDNESDAY || THURSDAY || FRIDAY || SATURDAY || SUNDAY);
assert (dayOfWeek (-1, FALSE, 2, 4) != MONDAY || TUESDAY ||
WEDNESDAY || THURSDAY || FRIDAY || SATURDAY || SUNDAY);
assert (dayOfWeek (-2, FALSE, 2, 4) != MONDAY || TUESDAY ||
WEDNESDAY || THURSDAY || FRIDAY || SATURDAY || SUNDAY);
assert (dayOfWeek (-3, FALSE, 2, 4) != MONDAY || TUESDAY ||
WEDNESDAY || THURSDAY || FRIDAY || SATURDAY || SUNDAY);
testNumber++;
testPrint (testNumber);
//Test for every 3rd of Ludvig A. Løddesøls birthdays
printf ("Test for every 3rd of Ludvig A. Løddesøls birthdays\n");
assert (dayOfWeek (MONDAY, TRUE, 3, 12) == SATURDAY);
assert (dayOfWeek (FRIDAY, FALSE, 3, 12) == WEDNESDAY);
assert (dayOfWeek (TUESDAY, TRUE, 3, 12) == SUNDAY);
assert (dayOfWeek (FRIDAY, FALSE, 3, 12) == WEDNESDAY);
assert (dayOfWeek (TUESDAY, FALSE, 3, 12) == SUNDAY);
assert (dayOfWeek (SATURDAY, FALSE, 3, 12) == THURSDAY);
assert (dayOfWeek (WEDNESDAY, FALSE, 3, 12) == MONDAY);
assert (dayOfWeek (SATURDAY, FALSE, 3, 12) == THURSDAY);
testNumber++;
testPrint (testNumber);
// Test for my birthday last 10 year
printf ("Test for my birthday last 10 year\n");
assert (dayOfWeek (SATURDAY, FALSE, 11, 18) == WEDNESDAY);
assert (dayOfWeek (FRIDAY, FALSE, 11, 18) == TUESDAY);
assert (dayOfWeek (THURSDAY, FALSE, 11, 18) == MONDAY);
assert (dayOfWeek (WEDNESDAY, TRUE, 11, 18) == SUNDAY );
assert (dayOfWeek (MONDAY, FALSE, 11, 18) == FRIDAY );
assert (dayOfWeek (SUNDAY, FALSE, 11, 18) == THURSDAY);
assert (dayOfWeek (SATURDAY, FALSE, 11, 18) == WEDNESDAY );
assert (dayOfWeek (FRIDAY, TRUE, 11, 18) == TUESDAY);
assert (dayOfWeek (WEDNESDAY, FALSE, 11, 18) == SUNDAY);
assert (dayOfWeek (TUESDAY, FALSE, 11, 18) == SATURDAY);
testNumber++;
testPrint (testNumber);
// Test 1st of Jan on some special year
printf ("Test 1st of Jan on some special year\n");
assert (dayOfWeek (TUESDAY, TRUE, 1, 1) == SATURDAY); // year 2000
assert (dayOfWeek (WEDNESDAY, FALSE, 1, 1) == MONDAY); // year 1900
testNumber++;
testPrint (testNumber);
}
Download file:
doomsday.c
(12.6 KB)