Art Calendar Sheets
Autumn Tournament (2014)
Submission name: calendar.cpp
Problem summary
A tear-off art calendar uses one page per weekday and one shared page for each Saturday–Sunday pair. Sheets have a front and back. The chronological first half appears on fronts, followed by a Flip front; after turning the stack, dates continue on backs in reverse sheet order. Given a year, its January1 weekday, and a date or Flip, print both sides of the corresponding sheet.
Input
Year, English January1 weekday, and day.month or Flip.
Output
Face: followed by its date(s) and weekday(s), or Flip; then Back: and its date(s). Omit a blank side. Dates use two-digit day and month.
Constraints
A valid year in the present or previous century and a valid date in that year; Gregorian leap-year rules.
Worked example
Original statement sample.
Input
2014 Wednesday 28.02
Output
Face: 28.02 Friday Back: 03.11 Monday
Solution analysis
- Generate every date in order using month lengths and the supplied January1 weekday. When a Sunday follows a Saturday within the year, put it on the same page. A January1 Sunday or December31 Saturday is a one-date boundary page.
- Let P be the number of dated pages and h=floor(P/2). There are h dated fronts and then a Flip front on sheet h, with sheets numbered from zero. Reversing the stack means back pages run in decreasing sheet order: sheet i has back page 2h−i. If that index is P, the back is blank.
- Find the page containing the requested date. A front-half page identifies its sheet directly; a back-half page identifies sheet 2h−pageIndex. For Flip use sheet h. In 2014, the sheet with front28.02 Friday has back03.11 Monday; the Flip sheet has back02.07 Wednesday. The provided weekday, rather than a second independent weekday calculation, drives the construction.
Why it works
Combining Saturday and Sunday yields exactly the specified chronological dated pages. The first h pages occupy successive fronts. Flipping the stack reverses sheet order, so assigning subsequent pages to backs from sheet h down to zero gives the formula2h−i. Finding either side therefore identifies its unique physical sheet and both required outputs.
Watch out. Do not pair a Sunday with a Saturday outside the given year. Use the supplied weekday of January1. Handle leap years and the possible blank back. A shared weekend page prints both dates, even if only Sunday was queried.
Commented C++17 solution
An independently written complete program with standard headers.
#include<array>
#include<iomanip>
#include<iostream>
#include<string>
#include<vector>
using namespace std;
struct Date{
int day;
int month;
int weekday;
};
void printPage(const string&label,const vector<Date>&page,const array<string,7>&names){
cout<<label;
for(const Date&date:page){
cout<<' '<<setfill('0')<<setw(2)<<date.day<<'.'<<setw(2)<<date.month;
cout<<' '<<names[date.weekday];
}
cout<<'\n';
}
int main(){
int year;
string firstWeekday;
string query;
cin>>year>>firstWeekday>>query;
array<string,7>names={"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"};
int weekday=0;
while(names[weekday]!=firstWeekday){
weekday++;
}
array<int,12>lengths={31,28,31,30,31,30,31,31,30,31,30,31};
if(year%400==0||(year%4==0&&year%100!=0)){
lengths[1]=29;
}
vector<vector<Date>>pages;
for(int month=1;month<=12;month++){
for(int day=1;day<=lengths[month-1];day++){
Date date{day,month,weekday};
if(weekday==6&&!pages.empty()&&pages.back().back().weekday==5){
pages.back().push_back(date);
}
else{
pages.push_back({date});
}
weekday=(weekday+1)%7;
}
}
int half=static_cast<int>(pages.size())/2;
int sheet=half;
if(query!="Flip"){
size_t dot=query.find('.');
int wantedDay=stoi(query.substr(0,dot));
int wantedMonth=stoi(query.substr(dot+1));
for(int page=0;page<static_cast<int>(pages.size());page++){
for(const Date&date:pages[page]){
if(date.day==wantedDay&&date.month==wantedMonth){
sheet=page<half?page:2*half-page;
}
}
}
}
// The Flip front is the final front before reversing the stack.
if(sheet==half){
cout<<"Face: Flip\n";
}
else{
printPage("Face:",pages[sheet],names);
}
int back=2*half-sheet;
if(back<static_cast<int>(pages.size())){
printPage("Back:",pages[back],names);
}
}