Clock and calendar arithmetic (modulo and periodicity)
- Module
- M3.8
- Lesson
- 1 of 1
- Reading time
- 4 min
In this lesson
- Use modulo to work with periodic data like hours, days, and weeks.
- Solve time-addition problems by adding and using modulo.
- Recognize periodicity in data and apply modulo to reduce it.
- Use modulo to handle wrap-around (circular) sequences.
Hours on a clock repeat every 12 or 24 hours. Days of the week repeat every 7 days. Many real-world problems involve this kind of cycling. You can use modulo to handle the wrap-around cleanly.
Modulo finds the remainder after division. In Python, a % b gives the remainder when a is divided by b. For positive numbers, the result is always between 0 and b - 1.
Working with modulo
Think of a 12-hour clock. After hour 11 comes hour 0. If it is now 10 o'clock and you add 5 hours, what time is it?
10 + 5 = 1515 % 12 = 3It is 3 o'clock. The modulo wraps the result back into the valid range 0 to 11.
On a clock with 24 hours, you use modulo 24. In a week with 7 days, you use modulo 7. The modulus is the period of the cycle.
Modulo is powerful because it handles wrap-around without explicit conditionals or loops. Instead of writing code that counts 10, 11, 12, 0, 1, 2, 3, you just compute (10 + 5) % 12. The modulo operation does the wrapping automatically. This makes code simpler and less error-prone. It also makes the algorithm clear: you are working with a cyclic structure.
Periodic scheduling
Say an event repeats every 3 days, starting on day 0. When does it occur? On days 0, 3, 6, 9, 12, and so on. Day d has the event if d % 3 == 0.
If the event starts on day 1 and repeats every 5 days, it occurs on days 1, 6, 11, 16, and so on. Day d has the event if (d - 1) % 5 == 0, or equivalently, if d % 5 == 1.
Here is a program that counts how many times a recurring event happens in a given number of days:
period = int(input())offset = int(input())days = int(input())
count = 0for d in range(days): if d % period == offset % period: count += 1
print(count)Input
3
1
10Output
3The program reads the period, the offset (which day the first event is on), and the total number of days. It counts how many multiples of the period, plus the offset, fall within the range.
Circular sequences
Modulo is useful for cycling through a list. If you have a list of items and want to index them in a repeating pattern, use modulo.
Days of the week are: Monday (0), Tuesday (1), ..., Sunday (6). If today is Tuesday (day 1) and you add 10 days, what day is it?
1 + 10 = 1111 % 7 = 4It is Friday (day 4). The modulo keeps the index in the valid range.
A calendar example
Modulo also handles longer calendars, not just a single week. Suppose day 0 of a year is a Monday, and a problem asks which day of the week day 100 falls on.
day_names = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]day_number = 100print(day_names[day_number % 7])100 % 7 is 2, so day_names[2] is "Wednesday". The same idea scales to any day count. A problem asking about day 10,000 needs no more work than one asking about day 10. The remainder after dividing by 7 is all that ever mattered, and computing it costs the same regardless of how large the day number gets. This is the same lookup-table pattern from an earlier lesson, with modulo supplying the index instead of the raw day number.
Handling large numbers with modulo
Modulo is also useful when numbers get very large. Suppose a machine cycles through states 0, 1, 2, 3, and then back to 0. After 1,000,000 cycles, which state is it in?
state = 1000000 % 4The answer is state 0. Without modulo, you would have to count 1 million steps. Modulo gives the answer instantly.
This applies to any repeating sequence. If you know the period, you can jump directly to the current position without simulating every step.
Common mistakes
One mistake is forgetting that modulo has a lower bound. In Python, a % b is always between 0 and b - 1 for positive b. If a is negative, the result can be negative. For time problems, keep your numbers positive. If you must work with negative numbers, add the modulus to shift them into range: (a % b + b) % b ensures a result between 0 and b - 1.
Another mistake is using the wrong modulus. If a pattern repeats every 12 hours, use modulo 12. If it repeats every 7 days, use modulo 7. Confusing the cycle period causes wrong answers. Think carefully about what the period is before you write the code.
A third mistake is reducing each side with modulo but forgetting to reduce the sum. (a % m) + (b % m) can add up to as much as 2 * m - 2, which is outside the valid range 0 to m - 1. The safe pattern always applies modulo to the whole sum last: (a + b) % m, or, if you already reduced a and b separately for some other reason, ((a % m) + (b % m)) % m.
A fourth mistake is assuming modulo works with negative divisors. Always use a positive modulus. Modulo with negative divisors behaves differently across languages and is a source of bugs.
Modulo makes periodic problems simple. Whenever a problem describes a repeating cycle, a fixed number of hours, days, positions, or states, that keeps coming back around, reach for modulo. It turns a problem that looks like it needs a step-by-step simulation into one you can solve directly with arithmetic, no matter how large the numbers involved get.
Practice
Try these on the judges. Each link opens the problem on WMOJ or DMOJ.
- 2024 S1Hat Circle (opens on WMOJ in a new tab) WMOJ
Compare values at paired positions around a circular arrangement, wrapping the index with modulo.
- 2017 J4Favourite Times (opens on DMOJ in a new tab) DMOJ
Count occurrences of a periodic event across a long span, using cycles and a remainder.
Why DMOJ: A periodicity problem matching this lesson's cycle-and-remainder pattern.