The Next Palindrome Date
National Olympiad — National round (2010 season)
Submission name: date.cpp
Problem summary
Write dates as DD.MM.YYYY, padding one-digit days and months with zero. Ignoring dots, a palindrome date reads identically in both directions. Find the earliest palindrome date strictly after the given valid date.
Input
Day, month, and year as three integers.
Output
The next palindrome date in DD.MM.YYYY format.
Constraints
The input date is valid; 1001 ≤ year ≤ 3010.
Worked example
An independently prepared example for this explanation.
Input
24 4 2010
Output
11.02.2011
Solution analysis
- For a fixed four-digit year abcd, a palindrome must have day dc and month ba. Thus each year has at most one candidate; there is no need to enumerate every day.
- Starting with the input year, derive that candidate, check the Gregorian month length and leap-year rule, then require its chronological key to exceed the input date. The first valid candidate is the answer.
- For 2010 the candidate is 01.02.2010, which precedes 24.04.2010. The 2011 candidate is 11.02.2011 and is valid, so it is the first answer.
Why it works
Palindrome symmetry forces the day and month uniquely from each year. The validity checks discard exactly nonexistent calendar dates. Years are tested in increasing order and each surviving date must be strictly later than the input, so the first survivor is the earliest permissible date.
Watch out. The answer must be strictly later. Apply Gregorian leap years: divisible by 400, or divisible by 4 but not 100. Preserve leading zeros.
Commented C++17 solution
An independently written complete program with standard headers.
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
int day, month, year;
cin >> day >> month >> year;
int original = year * 10000 + month * 100 + day;
for (int candidateYear = year; ; candidateYear++) {
// Palindrome symmetry determines day and month from the year.
int candidateDay = candidateYear % 10 * 10 + candidateYear / 10 % 10;
int candidateMonth = candidateYear / 100 % 10 * 10 + candidateYear / 1000;
if (candidateMonth < 1 || candidateMonth > 12) {
continue;
}
int lengths[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
bool leap = candidateYear % 400 == 0 ||
(candidateYear % 4 == 0 && candidateYear % 100 != 0);
if (leap) {
lengths[1] = 29;
}
if (candidateDay < 1 || candidateDay > lengths[candidateMonth - 1]) {
continue;
}
int key = candidateYear * 10000 + candidateMonth * 100 + candidateDay;
if (key > original) {
cout << setfill('0') << setw(2) << candidateDay << '.';
cout << setw(2) << candidateMonth << '.' << setw(4) << candidateYear << '\n';
break;
}
}
}