#include <iostream>
using namespace std;

int ymdToWeekNumber (int y, int m, int d) {
  // reject out-of-range input
  if ((y < 1965)||(y > 2099)) 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 - 1965) * 5) / 4) % 7) - 3;
  // compute day of the year (in range 1-366)
  int doy = d;
  if (m > 1) doy += 31;
  if (m > 2) doy += (((y%4)==0) ? 29 : 28);
  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;
  // check for boundary conditions
  // 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 (cdn > 364) {
    // check for year beginning on Thurs.
    if (corr==3) return 53;
    // check for leap year beginning on Wed.
    if (((y%4)==0) && (corr==2)) return 53;
    // otherwise, there is no week 53
    return 1;
  }
  // if our calculation would give us "week 0",
  // then go to the previous year
  // and find out whether we are in week 52 or week 53
  if (cdn < 1) {
    // first, compute correction for the previous year
    corr = ((((y - 1966) * 5) / 4) % 7) - 3;
    // then, compute day of year with respect to that same previous year
    doy = d + (((y%4)==1)?366:365);
    // finally, re-compute the corrected day number
    cdn = corr + doy;
  }
  // compute number of weeks, rounding up to nearest whole week
  return ((cdn + 6) / 7);
}

int main() {
	cout << "Week number test\n";
	int y, m, d;
	srand(16028);
	for (int i=2020; i<=2050; i++) {
	  y=i;
	  m=1;
	  d=1;
	  cout << y << "/" << m << "/" << d << "  ";
	  cout << ymdToWeekNumber(y,m,d) << "\n";
	  m=1+(rand()%3);
	  d=2+(rand()%27);
	  cout << y << "/" << m << "/" << d << "  ";
	  cout << ymdToWeekNumber(y,m,d) << "\n";
	  m=4+(rand()%3);
	  d=1+(rand()%30);
	  cout << y << "/" << m << "/" << d << "  ";
	  cout << ymdToWeekNumber(y,m,d) << "\n";
	  m=7+(rand()%3);
	  d=1+(rand()%30);
	  cout << y << "/" << m << "/" << d << "  ";
	  cout << ymdToWeekNumber(y,m,d) << "\n";
	  m=10+(rand()%3);
	  d=1+(rand()%30);
	  cout << y << "/" << m << "/" << d << "  ";
	  cout << ymdToWeekNumber(y,m,d) << "\n";
	  m=12;
	  d=31;
	  cout << y << "/" << m << "/" << d << "  ";
	  cout << ymdToWeekNumber(y,m,d) << "\n";	  
	}
	return 0;
}