-1

I am trying to find the fourth Thursday of November (thanksgiving day) of any user inputted year. I used the following function to find the day of December 31'st of the previous year of user inputted year.

int yr;
int lastDayofDecember;
scanf("%i",&yr);
lastDayofDecember = (((yr-1)*365)+((yr-1)/4)-((yr-1)/100)+((yr-1)/400))%7;

where, lastDayofDecember = 0 : Sunday, 1 : Monday,......6:Saturday;

Now for year 2016, the last day was a Saturday i.e lastDayofDecember = 6, I added 5 to it to find the first thursday of January and added 304 to it to find the first Thursday of November (January 1 - November 1 is 304 days for non-leap year) to which I added 21 to find the fourth thursday of November, but now I am confused about what to do next. I can not use loops

    int txDay = 5 + 304 + 21;
San Mo
  • 31
  • 5
  • I would construct the date November 1 (for whatever year) in a `struct tm`, then call `mktime` to fill in `tm_wday`, then work from there. – Steve Summit Oct 23 '17 at 11:26
  • @SteveSummit: I'd do similar, but using November 21. – Brendan Oct 23 '17 at 11:28
  • @SteveSummit I can not use `struct` since it is a school assignment. But I am using user defined functions to work this problem out. – San Mo Oct 23 '17 at 11:29
  • `int thanksGivingDayOfMonth=28-(5+year+year/4-year/100+year/400)%7;` (now you only need to explain this) –  Oct 23 '17 at 12:26
  • @FelixPalmen this calculates what day is the last day of the given `year`. `0=Sunday`,`1=Monday` and so on till `6=Saturday`. – San Mo Oct 23 '17 at 12:32
  • @SanMo I think you didn't understand my comment. –  Oct 23 '17 at 12:33
  • @FelixPalmen Oh I got it now, sorry been up all night trying to figure this out haha – San Mo Oct 23 '17 at 12:35
  • @SanMo still it only helps you when you **can** explain it. It's not that hard though. –  Oct 23 '17 at 12:47
  • @FelixPalmen Yes I am trying to figure out the logic behind the code you gave me. Thanks a lot. – San Mo Oct 23 '17 at 12:50
  • @SanMo I added an explanation –  Oct 23 '17 at 13:40

1 Answers1

0

Breaking this down, although it's not directly about programming, it's an interesting topic -- assuming the gregorian calendar only *):

As the week day advances by one per year, it can be calculated using a simple modulo 7 of the year. The only problem here are leap years, and you already have the formula to accomodate for these.

You're effectively doing calculations in the Ring 7 so you just have to add the number of leap years until your current year. Exploiting integer division, this number is

year/4 - year/100 + year/400

So, to get a unique number between 0 and 7 corresponding to one day of week each, you just do (year + year/4 - year/100 + year/400) % 7. This would be a bit more complicated for dates early in the year, but as we're interested in November, for leap years, the 29. February has already passed -> nothing more to do.

The latest possible date for thanksgiving day is the 28, when the 1. November is a Friday. So you want your calculated value to be 0 for years when November starts on a Friday. You can find by experimentation that you need to add an offset of 5 inside your Ring to achieve that. With that, you just need to subtract that value from this latest possible date, 28. This gives the complete formula:

int thanksGivingDate = 28 - (5 + year + year/4 - year/100 + year/400) % 7;

*) As this uses the rules of the gregorian calendar, the result will be incorrect for older dates still using the julian calendar. (e.g. 1752 and earlier for the U.S.)