#include <iostream>
using namespace std;
int days_in_month (int y, int m) {
// Fourth, eleventh, ninth, and sixth,
// thirty days to each we fix.
if ((m==4)||(m==11)||(m==9)||(m==6)) return 30;
// Every other, thirty-one,
// except the second month alone,
if (m!=2) return 31;
// which hath twenty-eight, in fine,
// till leap-year give it twenty-nine.
if ((y%400)==0) return 29; // leap year
if ((y%100)==0) return 28; // not a leap year
if ((y%4)==0) return 29; // leap year
return 28; // not a leap year
}
int ymdToWeekNumberA (int y, int m, int d) {
// reject out-of-range input
if ((y < 1583)||(y > 25000)) return 0;
if ((m < 1)||(m > 12)) return 0;
if ((d < 1)||(d > 31)) return 0;
// compute correction for year
// If Jan. 1 falls on: Mo Tu We Th Fr Sa Su
// then the correction is: 0 +1 +2 +3 -3 -2 -1
int corr = ((y + 2 + (y-1)/4 - (y-1)/100 + (y-1)/400) % 7) - 3;
// compute day of the year (in range 1-366)
int doy = d;
if (m > 1) doy += 31;
if (m > 2) doy += (((y%100) ? (y%4) : (y%400)) ? 28 : 29);
if (m > 3) doy += 31;
if (m > 4) doy += 30;
if (m > 5) doy += 31;
if (m > 6) doy += 30;
if (m > 7) doy += 31;
if (m > 8) doy += 31;
if (m > 9) doy += 30;
if (m > 10) doy += 31;
if (m > 11) doy += 30;
// compute corrected day number
int cdn = corr + doy;
// compute number of weeks, rounding up to nearest whole week
// this gives us our week number
int wknum = ((cdn + 6) / 7);
// check for boundary conditions:
// if our calculation would give us "week 0",
// then it is really the final week of the previous year
// and we need to find out whether that is week 52 or week 53
if (wknum < 1) {
// first, compute correction for the previous year
corr = ((y + 1 + (y-2)/4 - (y-2)/100 + (y-2)/400) % 7) - 3;
// then, compute day of year with respect to that same previous year
doy = d + ((((y-1)%100) ? ((y-1)%4) : ((y-1)%400)) ? 365 : 366);
// finally, re-compute the corrected day number and the week number
cdn = corr + doy;
wknum = ((cdn + 6) / 7);
return wknum;
}
// if our calculation would give us "week 53",
// we need to find out whether week 53 really exists,
// or whether it is week 1 of the following year
if (wknum > 52) {
// check for year beginning on Thurs.
if (corr==3) return 53;
// check for leap year beginning on Wed.
if ((((y%100)?(y%4):(y%400))==0) && (corr==2)) return 53;
// otherwise, there is no week 53
return 1;
}
return wknum;
}
int ymdToWeekNumberB (int y, int m, int d) {
if ((y < 1583)||(y > 25000)) return 0;
if ((m < 1)||(m > 12)) return 0;
if ((d < 1)||(d > 31)) return 0;
int adj = ((y + 2 + (y-1)/4 - (y-1)/100 + (y-1)/400) % 7) + 3;
int doy = d;
for (int i=1; i<m; i++) doy += (30 + ((0x15AA >> i) & 1));
if (m > 2) doy -= (((y%100) ? (y%4) : (y%400)) ? 2 : 1);
int wknum = (adj + doy) / 7;
if (wknum < 1) {
adj = ((y + 1 + (y-2)/4 - (y-2)/100 + (y-2)/400) % 7) + 3;
if (adj==9) return 53;
if ((adj==8) && ((((y-1)%100)?(y%4):(y%400))==1)) return 53;
return 52;
}
if (wknum > 52) {
if (adj==9) return 53;
if ((adj==8) && (((y%100)?(y%4):(y%400))==0)) return 53;
return 1;
}
return wknum;
}
int main() {
int yyyy=1583, mo=1, dd=3, wd=1, wn=1;
int wna, wnb;
int errcnta=0, errcntb=0;
while (yyyy<=25000) {
wna=ymdToWeekNumberA(yyyy,mo,dd);
wnb=ymdToWeekNumberB(yyyy,mo,dd);
if ((wn!=wna)||(wn!=wnb)) {
if ((errcnta<100)&&(errcntb<100)) {
cout << yyyy << "/" << mo << "/" << dd << " ";
cout << "W" << wn << "-" << wd << " ";
cout << "A=" << wna << " B=" << wnb << "\n";
}
if (wn!=wna) errcnta++;
if (wn!=wnb) errcntb++;
}
dd++;
if (dd>days_in_month(yyyy,mo)) {
dd=1;
mo++;
if (mo>12) {
mo=1;
yyyy++;
}
}
wd++;
if (wd>7) {
wd=1;
wn++;
if (((mo==12)&&(dd>=29))||((mo==1)&&(dd<=4))) wn=1;
}
}
cout << "Errors (A): " << errcnta << "\n";
cout << "Errors (B): " << errcntb << "\n";
// your code goes here
return 0;
}