First Try
I started with a simple while loop:
<?php
$sum = 0;
$x = 0;
$max = 1000;
while ( $x < $max ) {
if ( (0 === $x % 3) || ( 0 === $x % 5) ) {
$sum += $x;
}
/* increment so we can loop to the next value */
$x++;
}
print $sum;
Surely, this is non-optimal: how many times will this loop run? 1000? Surely we can reduce it!
Possible optimizations include:
- Start at 3 instead of 0!
- Surely we can skip numbers if we do find a multiple of 3 or 5? That is, keep adding 3 to previous number and sum the additions, same with 5.
OK, let’s do that.
Second Try
<?php
$threes = 0;
$fives = 0;
$x = 0;
$y = 0;
while ( $x < 1000 ) {
$x += 3;
$threes += $x;
}
while ( $y < 1000 ) {
$y += 5;
$fives += $y;
}
print $threes + $fives;
But, this is wrong because I didn’t factor out repeated numbers in this, such as those divisable by both 3*5 (i.e. 15)!
Final Solutions
#1. For Loop Summing
This uses a test nested within a for loop. The test contains two conditions and sums at once.
Some posted solutions for PHP append each sum into an array and then add them at the end. I think that takes more memory than addition+substitution in place.
<?php
function sum_for_loop(Array $terms, $max = 0) {
/* must have initialized variable so we can += below without PHP errors */
$sum = 0;
for ( $x=0; $x < $max; $x++ ) {
/* only sum factors of 3 or 5 */
if ( (0 === $x % $terms[0]) || ( 0 === $x % $terms[1]) ) {
$sum += $x;
}
}
return $sum;
}
Of course, this semi-generalized solution assumes that the $terms array will only have two elements. I’ll need to explore how to loop through the terms and handle them, possibly with code generation?
#2. Arithmetic Series
This solution reflects the spirit of the canonical solution contained in Project Euler’s PDF.
It is, by far, the most efficient algorithm.
<?php
function sum_arithmetic($multiple = 1, $limit = 0) {
$max_term = intval(($limit - 1) / $multiple);
return ($multiple * ($max_term * ($max_term + 1))) / 2;
}
The parentheses placement were key…
Leave a comment