in reply to Pythagorean's theorem

Not bad. But note that at the moment you are getting duplicates - e.g. (4,3,5) and (3,4,5). You could avoid this, and speed your code up significantly, by replacing

for ($b=1; $b<$max; $b++) {
with
for ($b=$a; $b<$max; $b++) {

You might also want to avoid your third embedded loop. It doesn't matter much if you do pythagoras.pl 10, but pythagoras.pl 1000 is sloooooooow.

You already know a and b, so you just need to test if a^2 + b^2 is a perfect square. For that you probably need one of the Math modules.

Update

Doh! You can just do **(1/2) to get the square root. Back to maths class for me. Although, will integer handling bite you in the ass if you just do

my $h = ($a**2 + $b**2) ** (1/2); if ($h == int $h) { print "$a $b $h is a winner\n"; }

? I don't know. Answers on a postcard.

dave hj~

Replies are listed 'Best First'.
Re: Re: Pythagorean's theorem
by fuzzyping (Chaplain) on Feb 27, 2002 at 17:16 UTC
    Thanks for the tip on $b=$a... although I was looking for all possible permutations (ok to switch values for $a and $b), it helps to only grab unique. Guess I could toss an ARGV in for "uniqueness".

    As far as the square root, you could also use the built-in sqrt() function. Although yes, I'm still trying to alleviate the float problem (without using modules). ;-)

    -fuzzyping

    UPDATE:

    Just realized my original logic with the $c loop was greatly flawed as well... it's limited by $max. For example, where $max=10, it should find:

    3 4 5 is a winner
    6 8 10 is a winner

    But it was only finding /3 4 5/ due to the limit on $c (duh). Removing the $c loop has helped, but required me to cheat on the final confirmation (I didn't want to use any modules). Using sqrt and then avoiding any floats is the answer, but requires that I test $c as a string. :-(

    #!/usr/bin/perl use strict; my ($a, $b, $c); my $max = shift || die "Usage: pythag.pl <max len>\n"; for ($a=1; $a<$max; $a++) { for ($b=$a; $b<$max; $b++) { $c = sqrt(($a**2) + ($b**2)); unless ($c =~ /\./) { print "$a $b $c is a winner\n"; } } }
    The final result is only one line smaller, but saves .243ms per successful match.

    -fuzzyping

    UPDATE:

    Thanks to tye and Sinister (don't know how I missed it before), I've implemented the int() check instead (keeping it within the numeric handling constraints I prefer)...

    #!/usr/bin/perl use strict; my ($a, $b, $c); my $max = shift || die "Usage: pythag.pl <max len>\n"; for ($a=1; $a<$max; $a++) { for ($b=$a; $b<$max; $b++) { $c = sqrt(($a**2) + ($b**2)); if (int($c) == $c) { print "$a $b $c is a winner\n"; } } }
    Thanks to all!

    -fuzzyping