cppAcademy
FROM LEARNING TO COMPETING

Real problems.
Your next challenge.

Explore the Group C Olympiad and Autumn Tournament archive.
Choose a topic. Find a challenge. Build your solution.

274 tasks: 213 from the Municipal, Regional, and National Olympiad rounds (2009–2026), 57 Autumn Tournament tasks (2007–2025), and 4 previously featured problems. 207 tasks have independently written English summaries, analyses, and C++17 solutions; the remaining entries link to Arena. Difficulty labels are learning estimates, not official ratings. Special formats and source clarifications are explained on affected tasks.
GROUP C2014 · MediumCalendar simulation

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

  1. 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.
  2. 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.
  3. 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.

Complexity: O(Y) time and space, where Y is365 or366. Generating and searching at most366 dates is effectively constant for one query.

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);
    }
}

Source: Arena Olimpiici ↗