The Cuckoo Clock
National Olympiad — Regional round (2015 season)
Submission name: kuku.cpp
Problem summary
At every exact hour a cuckoo calls the corresponding 12-hour hour number (12 at midnight and noon); at every half hour it calls once. Count the calls in the given interval, which may cross midnight. Use a both-endpoints-inclusive interval.
Source clarification. The PDF does not explicitly state endpoint inclusion. Official tests in https://infos.infosbg.com/files/Contests/NOI-2/2015/E/problems/kuku.zip resolve this: 12:00–12:30 yields 13 calls and 12:00–13:00 yields 14. Both endpoints are included here.
Input
Start hour, start minute, end hour, end minute.
Output
The number of cuckoo calls.
Constraints
Hours 0–23, minutes 0–59; duration is positive and less than 24 hours.
Worked example
An independently prepared example for this explanation.
Input
5 20 10 25
Output
45
Solution analysis
- Convert both endpoints to minutes. If the end comes before the start, add 1440 to it, giving a forward interval on a continuous time line.
- Visit each minute t from the start through the end, inclusive. At minute 30 of an hour add one. At minute 0 add the hour modulo 12, replacing zero with 12.
- From 05:20 to 10:25 the half-hour calls are at 05:30 through 09:30, contributing 5. The exact hours 06:00 through 10:00 contribute 6 + 7 + 8 + 9 + 10 = 40, for 45 in total. The reverse interval crosses midnight and gives 135.
Why it works
Each possible calling time is an exact minute, so the loop visits every event in the chosen interval exactly once. The minute and hour conditions assign precisely the specified number of calls to each event; other minutes contribute zero. Their sum is therefore correct.
Watch out. Use 12 rather than 0 for midnight and noon. Overnight intervals need the next-day endpoint. Endpoint convention matters at exact hours and half hours.
Commented C++17 solution
An independently written complete program with standard headers.
#include <iostream>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int h1, m1, h2, m2;
cin >> h1 >> m1 >> h2 >> m2;
int start = h1 * 60 + m1;
int end = h2 * 60 + m2;
if (end < start) {
end += 1440;
}
int answer = 0;
// Official boundary tests count events at both endpoints.
for (int t = start; t <= end; ++t) {
if (t % 60 == 30) {
++answer;
} else if (t % 60 == 0) {
int hour = (t / 60) % 12;
answer += hour == 0 ? 12 : hour;
}
}
cout << answer << '\n';
return 0;
}