How to loop through an array with a variable starting element
Published: 2023-10-17 11:21:41

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

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2t5bblwmbf43toh6twyh.png)

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):

```php
$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`.

```php
$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](https://en.wikipedia.org/wiki/Modular_arithmetic). 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:

1. the result is always less than or equal to the dividend (`5`)
2. 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:

```php
$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:

```php
$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.