doomsday.c - OpenLearning
/*
 *  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)

Comments

Chat