Recently I was faced with an interesting problem. I needed to create a simplified (pseudo-) cron interface:

The task is to find the next selected day.

My first attempt was a naive one. Loop to the end of the array and if nothing was found, start a second loop at the beginning and move to the current day (pseudocode, no error detection, performance optimization or edge casing):

$days = Array(false, true, false, true, false, false, false); $today = 4 // Thursday $i = today + 1; // loop index starts at the next day (Friday) $next = -1; // loop abort variable // iterate to the end of the array while ($i <= $today.length() && $next == -1) { if ($days[i] == true) { // day checkbox is selected $next = $days[$i]; } $i++; } // no truthy element was found if ($next == -1) { $i = 0; // start at the beginninf of the array // iterate from the start to the current day while ($i <= $today && $next == -1) { if ($days[i] == true) { // day checkbox is selected $next = $i; } $i++; } } print $next; // 1 (Monday)

The problem can be abstracted: Printing all the indices of an array in sequence, using a variable starting point. In the example above:

.`5, 6, 0, 1, 2, 3, 4`

$start = 4; $arr = Array(false, true, false, false, true, false, false); $max = $arr.length; $i = $start + 1 ; while ($i < $max) { print ($i); // 5, 6 $i++; } $i = 0; while ($i < $start + 1) { print ($i); // 0, 1, 2, 3, 4 $i++; }

If you look at the output, you’ll notice that the numbers are all integers and less than or equal to ``max`

.

There’s a special, lesser-known operator that comes in handy in this case: modulo. In a nutshell, modulo returns the integer remainder of a division, e.g:

- 1 mod 5 → 1 (0 remaining 1)
- 2 mod 5 → 2 (0 remaining 2)
- 3 mod 5 → 3 (0 remaining 3)
- 4 mod 5 → 4 (0 remaining 4)
- 5 mod 5 → 0 (1 remaining 0)
- 6 mod 5 → 1 (1 remaining 1)
- 7 mod 5 → 2 (1 remaining 2)

You will notice two things:

- the result is always less than or equal to the dividend (
`5`

) - the result is repeated after the dividend (
`1, 2, 3, 4, 5, 6, 7`

) exceeds the value of the divisor (`5`

).

That’s exactly what we need. Let’s put something like this, with different numbers, into code:

$start = 4; $max = 7; $i = $start; while ($i < $max + $start) { print ($i); // 4, 5, 6, 7, 8, 9, 10 print ($i mod $max); // 4, 5, 6, 0, 1, 2, 3 $i++; }

The index `i`

exceeds the length of the array, but we’re using `i mod max`

and not the loop index itself. The result makes a round trip after reaching `max`

and starts again at `0`

. All indexes of the array are covered, starting from the middle index

.`4`

The actual code now looks like this:

$days = Array(false, true, false, true, false, false, false); $today = 4 // THursday $i = $today + 1; $max = $days.length; $next = -1; while ($i < $max + $today && $next == -1) { if ($days[$i mod $max] == true) { $next = i mod $max; } $i++; } print ($next); // 1 (Monday)

This code may not look as readable as before, so why are we doing this?

Because we can!

And it’s fun to come up with a clever solution to a problem. We’re programmers, after all.

Foto by Philip Veater on Unsplash