This is another Project Euler puzzle I hadn’t tried before. I’m doing these as a simple practical exercise for teaching myself PHP, and I’d appreciate any feedback on my code.
If p is the perimeter of a right angle triangle with integral length sides, {a,b,c}, there are exactly three solutions for p = 120.
{20,48,52}, {24,45,51}, {30,40,50}
For which value of p ≤ 1000, is the number of solutions maximised?
Here’s my code, I’m not sure it’s particularly efficient, taking a brute force approach to working out all the hypotenuses for rightangled triangles with sides adding up to 1000.
<?php $solutions = []; $limit = 1000; for ($adjacent = 1; $adjacent <= $limit; $adjacent++) { for ($opposite = 1; $opposite <= $limit; $opposite++) { $hypotenuse = sqrt(pow($adjacent, 2) + pow($opposite, 2)); if ($hypotenuse != round($hypotenuse)) { continue; } $perimiter = $hypotenuse + $adjacent + $opposite; if ($perimiter > $limit) { break; } if (isset($solutions[$perimiter])) { $solutions[$perimiter]++; } else { $solutions[$perimiter] = 1; } } } arsort($solutions, SORT_NUMERIC); echo key($solutions);
I found I was able to slightly optimise the code postcompletion by amending:
for ($adjacent = 1; $adjacent <= $limit; $adjacent++) { for ($opposite = 1; $opposite <= $limit; $opposite++) {
to:
for ($adjacent = 1; $adjacent <= $limit/2; $adjacent++) { for ($opposite = 1; $opposite <= $limit/2; $opposite++) {
… but this was just through trialanderror without any real thought as to why exactly. Obviously I didn’t need to loop all the way up to the limit for the length of either individual side. In fact I could amend the outer loop to only go up to $limit/3 although that was more luck than anything; for the test limit of 120 that didn’t work.
I only wanted to work with values where the hypotenuse was an integer. For some reason the is_int() and is_float() functions didn’t seem to work for me, so I had to use round() to check the value was identical to its integer component.
I then increment the count of how many solutions there are for this length of perimiter. After the loop I use arsort() to reversesort on value (keeping the associated keys), and key() to output the value of the first element of the array.
Make sure not to confuse arsort with the multitude of other functions that sort arrays, including:

sort — Sort an array

rsort — Sort an array in reverse order

asort — Sort an array and maintain index association

arsort — Sort an array in reverse order and maintain index association

ksort — Sort an array by key

krsort — Sort an array by key in reverse order

natsort — Sort an array using a “natural order” algorithm

natcasesort — Sort an array using a case insensitive “natural order” algorithm

array_multisort — Sort multiple or multidimensional arrays

usort — Sort an array by values using a userdefined comparison function

uksort — Sort an array by keys using a userdefined comparison function

uasort — Sort an array with a userdefined comparison function and maintain index association
Phew!
Leave a Reply