First School Day after a Holiday
National Olympiad — Regional round (2019 season)
Submission name: grip.cpp
Problem summary
A holiday starts on a given date and lasts a number of Monday–Friday school days, including its start when it is a weekday. Find the first school day afterwards.
Input
D/M/Y and school-day duration.
Output
Return date dd.mm.yyyy.
Constraints
Start date in 2019 or 2020; duration 1…45 school days.
Worked example
Input and output for the worked example discussed below.
Input
23/1/2019 8
Output
04.02.2019
Solution analysis
- Track calendar date and weekday together. January 1,2019 was Tuesday; advancing from it determines the starting weekday.
- Consume a holiday day only on Monday–Friday, always moving one calendar day. After all required days are consumed, skip any following weekend. Gregorian leap-year rules determine February’s length.
- Starting Wednesday January 23, eight school days end on Friday February 1. The next weekday is Monday February 4. A weekend start consumes no school day until Monday.
Why it works
The simulation consumes exactly the requested weekdays and then returns the earliest subsequent weekday.
Watch out. Handle February 29,2020, year rollover and zero padding.
Commented C++17 solution
An independently written complete program with standard headers.
// The simulation consumes exactly the requested weekdays and then returns the earliest subsequent weekday.
#include<iomanip>
#include<iostream>
using namespace std;
bool leap(int year){
return year%400==0||(year%4==0&&year%100!=0);
}
void nextDay(int&day,int&month,int&year,int&weekday){
const int lengths[12]={31,28,31,30,31,30,31,31,30,31,30,31};
int limit=lengths[month-1]+(month==2&&leap(year));
day++;
if(day>limit){
day=1;
month++;
if(month==13){
month=1;
year++;
}
}
weekday=(weekday+1)%7;
}
int main(){
int targetDay,targetMonth,targetYear,remaining;
char separator;
cin>>targetDay>>separator>>targetMonth>>separator>>targetYear>>remaining;
int day=1;
int month=1;
int year=2019;
int weekday=1;
while(day!=targetDay||month!=targetMonth||year!=targetYear){
nextDay(day,month,year,weekday);
}
while(remaining>0){
if(weekday<5){
remaining--;
}
nextDay(day,month,year,weekday);
}
while(weekday>=5){
nextDay(day,month,year,weekday);
}
cout<<setfill('0')<<setw(2)<<day<<'.'<<setw(2)<<month<<'.'<<year<<'\n';
}