Algo Solution
There is a way to check if there is a missing number using an algorithm. He explained here . Basically, if we need to add numbers from 1 to 100. We do not need to calculate by summing them, we just need to do the following: (100 * (100 + 1)) / 2 . So how does this solve the problem?
We are going to get the first element of the array and the last. We calculate the sum with this algorithm. Then we use array_sum() to calculate the actual amount. If the results match, then the missing number is missing. Then we could “step back” from the missing number by subtracting the actual amount from the estimated amount. This, of course, only works if there is only one number, and it will fail if there are several missing ones. So put this in code:
$range = range(0,7); // Creating an array echo check($range) . "\r\n"; // check unset($range[3]); // unset offset 3 echo check($range); // check function check($array){ if($array[0] == 0){ unset($array[0]); // get ride of the zero } sort($array); // sorting $first = reset($array); // get the first value $last = end($array); // get the last value $sum = ($last * ($first + $last)) / 2; // the algo $actual_sum = array_sum($array); // the actual sum if($sum == $actual_sum){ return $last + 1; // no missing number }else{ return $sum - $actual_sum; // missing number } }
Output
8 3
Online demo
If numbers are missing, just use array_map() or something similar to the inner loop.
Regression solution
Take it to the next level and use regex! I know this is nonsense and should not be used in the real world. The goal is to show the true power of the regular expression :)
So, first we make a line from our range in the following format: I,II,III,IIII for range 1,3 .
$range = range(0,7); if($range[0] === 0){ // get ride of 0 unset($range[0]); } $str = implode(',', array_map(function($val){return str_repeat('I', $val);}, $range)); echo $str;
The output should look something like this: I,II,III,IIII,IIIII,IIIIII,IIIIIII .
I got the following regular expression: ^(?=(I+))(^\1|,\2I|\2I)+$ . So what does this mean?
^
Let's see what actually happens ....
I,II,III,IIII,IIIII,IIIIII,IIIIIII ^ (I+) do not eat but match I and put it in group 1 I,II,III,IIII,IIIII,IIIIII,IIIIIII ^ ^\1 match what was matched in group 1, which means I gets matched I,II,III,IIII,IIIII,IIIIII,IIIIIII ^^^ ,\2I match what was matched in group 1 (one I in thise case) and add an I to it I,II,III,IIII,IIIII,IIIIII,IIIIIII ^^^^ \2I match what was matched previously in group 2 (,II in this case) and add an I to it I,II,III,IIII,IIIII,IIIIII,IIIIIII ^^^^^ \2I match what was matched previously in group 2 (,III in this case) and add an I to it We're moving forward since there is a + sign which means match one or more times, this is actually a recursive regex. We put the $ to make sure it the end of string If the number of I don't correspond, then the regex will fail.
See how it works and doesn't work . And put it in your PHP code :
$range = range(0,7); if($range[0] === 0){ unset($range[0]); } $str = implode(',', array_map(function($val){return str_repeat('I', $val);}, $range)); if(preg_match('#^(?=(I*))(^\1|,\2I|\2I)+$#', $str)){ echo 'works !'; }else{ echo 'fails !'; }
Now let’s take an account to return a number that is missing, we will remove the end $ character so that our regular expression doesn’t work, and we use group 2 to return the missing number:
$range = range(0,7); if($range[0] === 0){ unset($range[0]); } unset($range[2]); // remove 2 $str = implode(',', array_map(function($val){return str_repeat('I', $val);}, $range)); preg_match('#^(?=(I*))(^\1|,\2I|\2I)+#', $str, $m); // REGEEEEEX !!! $n = strlen($m[2]); //get the length ie the number $sum = array_sum($range); // array sum if($n == $sum){ echo $n + 1; // no missing number }else{ echo $n - 1; // missing number }
Online demo