Duncan has mused me again. He's reworking his Project Euler exercises that he'd previously done in CFML, and is now implementing in PHP. In yesterday's exercise he was looking at prime numbers: "Project Euler: problem 7 (PHP)". I thought there was scope for another exercise in using PHP generators in this for me (see previous: "PHP: generators").
So I've come up with this implementation:
<?php
// primes.php
function createPrimeSequence($length=-1)
{
$primes = [];
$potential = 1;
while ($length==-1 || sizeof($primes) < $length) {
$potential++;
$upperThreshold = sqrt($potential);
foreach($primes as $prime){
if ($prime > $upperThreshold){
break;
}
if ($potential % $prime == 0){
continue 2;
}
}
$primes[] = $potential;
yield end($primes);
}
}
$primesSequence = createPrimeSequence();
for ($i=1; $i <= 20; $i++){
echo $primesSequence->current() . " ";
$primesSequence->next();
}
echo "<hr>";
foreach(createPrimeSequence(10) as $prime){
echo "$prime ";
}
The prime calculation logic is pedestrian so I'll ignore that, the new conceit here is that I've added a
$length
argument to define a... well... length to the sequence, rather than it just continuing forever, as it did in the Fibonacci example. This means I can use it directly in a foreach()
loop.Oh, this outputs:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71
2 3 5 7 11 13 17 19 23 29
New stuff I learned whilst doing this:
- how PHP emulates optional arguments by being able to specify a default. It seems one cannot have a truly optional argument though.
sqrt()
is PHP's square root function.- Both
break
andcontinue
can exit multiple levels of looping, by specifying a number of levels to exit from (default is1
). Here I usecontinue 2
to break out of the innerforeach()
loop, but also jump out of the current iteration of thewhile()
loop. - the
$array[]
syntax is shorthand forarray_push($array)
end()
returns the last entry in an array, differing fromarray_pop()
as it leaves the array intact.
--
Adam