Yeah, I know this is a very simple piece of code... but I don't have anything else in my reportoire worth posting right now. ;-)

Feed it an integer, and it will print all possible permutations ($a/$b/$c) of right triangles.
#!/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=1; $b<$max; $b++) { for ($c=1; $c<$max; $c++) { if ((($a**2) + ($b**2)) == ($c**2)) { print "$a $b $c is a winner\n"; } } } }
-fuzzyping

Replies are listed 'Best First'.
Re: Pythagorean's theorem
by dash2 (Hermit) on Feb 27, 2002 at 14:03 UTC
    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~

      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
Re: Pythagorean theorem
by I0 (Priest) on Feb 27, 2002 at 21:46 UTC
    #!/usr/bin/perl use strict; my $max = shift or die "Usage: $0 <max len>\n"; for my $t ( 2..$max ){ for my $s ( 1..$t-1 ){ print $t*$t-$s*$s," ",2*$s*$t," ",$t*$t+$s*$s," is a winner\n" +; } }
      Definitely something amiss here. It doesn't limit the arg like it should. For example, where $max=10, it pushes side "b" as high as 180.

      -fuzzyping
        #!/usr/bin/perl use strict; my $max = shift or die "Usage: $0 <max len>\n"; for my $t ( 2..sqrt$max ){ for my $s ( 1..$t-1 ){ my $c=$t*$t+$s*$s; next unless $c <= $max; my $a = $t*$t-$s*$s; my $b = 2*$s*$t; print "$a $b $c is a winner\n"; } }