Duncan's blog

October 26, 2014

Project Euler: problem 80 (PHP) – Square root digital expansion

Filed under: PHP,Project Euler — duncan @ 11:41 am
Tags: ,

80I’m doing these Project Euler mathematical puzzles as a simple practical exercise for teaching myself PHP, and I’d appreciate any feedback on my code.

Problem 80:

It is well known that if the square root of a natural number is not an integer, then it is irrational. The decimal expansion of such square roots is infinite without any repeating pattern at all.

The square root of two is 1.41421356237309504880…, and the digital sum of the first one hundred decimal digits is 475.

For the first one hundred natural numbers, find the total of the digital sums of the first one hundred decimal digits for all the irrational square roots.

So this Euler puzzle has only been solved by a little over 10,000 people at the current point, a relatively low number, from which I surmise this is conceivably the hardest puzzle I’ve solved.  In reality it wasn’t that hard however, thanks to PHP’s BC Maths functions.

<?php
$sum = 0;

for ($number = 1; $number <= 100; $number++) {
	$root = bcsqrt($number, 99);
	
	if ($root != round($root)) {
		$decimal = explode(".", $root);
		
		$sum += $decimal[0];
		$sum += array_sum(str_split($decimal[1]));
	}
}

echo $sum;

Using bcsqrt() to calculate the square root of every number from 1 to 100, and I’ve specified 99 as the scale parameter, for how many digits after the decimal point I want.

I’m still not having any luck with the is_int() function, so comparing the value to its integer version using round() to see if we’re dealing with integers or irrational numbers.  Initially I didn’t think I would need to do this, as things like bcsqrt(4, 99) would return 2.000…  so adding all those zeroes wouldn’t affect my total.  However bcsqrt(1, 99) just returns 1, not 1.000… which caused an error further down in the code when using explode(), as there wasn’t any decimal point in the value.

I then turn the number into an array using explode(), splitting it on the decimal point.  I add the integer part.  Then I use str_split() to convert decimals like 4142… into arrays like [4, 1, 4, 2, …].  And then array_sum() to total up all those digits.  If we were dealing with numbers any greater than 100 then I’d need to do the same with the integer value, but otherwise I know we’re never going to have values with the integer part more than 1 digit long.

Initially I thought when it said the digital sum of the first one hundred decimal digits that it meant the first 100 digits after the decimal point.  e.g. for the square root of 2 (1.4142…) it would be 4 + 1 + 4 + 2… etc.  However I wasn’t getting the right answer.  Comparing the value I was getting for adding up the digits of the square root of 2  with the answer they’d given for that (475), I was able to see where I’d gone wrong.  They really meant just the first 100 digits of the value, including the integer part, e.g. 1 + 4 + 1 + 4 + 2… etc.

So to cater for that I reduced the scale on the bcsqrt() from 100 to 99 and also added the integer part of each square root.

Create a free website or blog at WordPress.com.