I'm currently working on a problem (Friday the thirteenth) on the USACO site and I've coded a program which, given a number N,computes how often the 13th lands on each day of the week from Jan 1st,1900 to Dec 31st,1900+N-1.The algorithm is inspired from a mental calculation trick : http://www.jimloy.com/math/day-week.htm
Things to keep in mind: January 1, 1900 was on a Monday. Thirty days has September, April, June, and November, all the rest have 31 except for February which has 28 except in leap years when it has 29. Every year evenly divisible by 4 is a leap year (1992 = 4*498 so 1992 will be a leap year, but the year 1990 is not a leap year) The rule above does not hold for century years. Century years divisible by 400 are leap years, all other are not. Thus, the century years 1700, 1800, 1900 and 2100 are not leap years, but 2000 is a leap year.*
The program works well except when N=256 (1900 to 2156) My program outputs : 440 438 439 439 437 439 440
while on USACO, there is: 440 439 438 438 439 439 439
The program takes a file (friday.in) containing N as input and outputs seven space separated integers representing the number of occurrences of each day (starting by Saturday) on one line in another file(friday.out).
I've put several cout for debugging purposes.
Here's the code:
/*
ID: freebie1
PROG:friday
LANG: C++
*/
#include <fstream>
#include <vector>
#include <iostream>
using namespace std;
class Date
{
public:
Date(int month=0,int year=0):m_month(month),m_year(year)
{
}
int monthDiff()
{
if(m_month<=3)
{
if(m_month==1)
{
return 0;
}
else if(m_month==2)
{
return 31;
}
}
if(m_month>=3)
{
if((m_year%4==0 && m_year%100!=0)||(m_year%100==0 && m_year%400==0))
{
if(m_month<9)
{
if(m_month%2==0)
return 60+(31*int(m_month/2.6)+30*(int(m_month/2.6)-1));
else
return 60+(61*int(m_month/3.5));
}
else if(m_month>=9)
{
if(m_month%2==0)
return 91+61*(m_month/3);
else
return 91+(31*int(m_month/2.75)+30*int(m_month/3.6));
}
}
else
{
if(m_month<9)
{
if(m_month%2==0)
return 59+(31*int(m_month/2.6)+30*(int(m_month/2.6)-1));
else
return 59+(61*int(m_month/3.5));
}
else if(m_month>=9)
{
if(m_month%2==0)
return 90+61*(m_month/3);
else
return 90+(31*int(m_month/2.75)+30*int(m_month/3.6));
}
}
}
}
void show()
{
cout<<m_month<<"/"<<m_year<<": ";
}
int tellDay()
{
int daysInYears=int((m_year-1900))*365;
int daysInMonths=this->monthDiff();
int leapDays;
if(m_year%4==0 && m_year!=1900)
leapDays=int((m_year-1900)/4)-1;
else if(m_year>2100)
leapDays=int((m_year-1900)/4)-1;
else if(m_year>2200)
leapDays=int((m_year-1900))/4-2;
else
leapDays=int((m_year-1900))/4;
int days=13+leapDays;
int res=daysInYears+daysInMonths+days;
cout<<"MonthDiff: "<<this->monthDiff()<<" In years: "<<daysInYears<<" days: "<<days<<" ";
return res%7;
}
private:
int m_month;
int m_year;
};
int main()
{
ifstream fin("friday.in");
ofstream fout("friday.out");
if(fin)
{
int n(0),day(0),sMonth(1),sYear(1900);
fin>>n;
vector<int> weekDays(7,0);
for(int i(0);i<n;i++)
{
for(int j(0);j<12;j++)
{
Date date(sMonth+j,sYear+i);
day=date.tellDay();
date.show();
cout<<day<<endl;
switch(day)
{
case 0:
weekDays[1]+=1;
break;
case 1:
weekDays[2]+=1;
break;
case 2:
weekDays[3]+=1;
break;
case 3:
weekDays[4]+=1;
break;
case 4:
weekDays[5]+=1;
break;
case 5:
weekDays[6]+=1;
break;
case 6:
weekDays[0]+=1;
break;
}
}
}
for(int i(0);i<6;i++)
{
fout<<weekDays[i]<<" ";
}
fout<<weekDays[6]<<endl;
}
return 0;
}