63 lines
1.3 KiB
Perl
63 lines
1.3 KiB
Perl
use strict;
|
||
use warnings;
|
||
use List::Util qw(max);
|
||
|
||
sub gcd { $_[1] == 0 ? $_[0] : gcd($_[1], $_[0] % $_[1]) }
|
||
|
||
sub hero {
|
||
my ($a, $b, $c) = @_[0,1,2];
|
||
my $s = ($a + $b + $c) / 2;
|
||
sqrt $s*($s - $a)*($s - $b)*($s - $c);
|
||
}
|
||
|
||
sub heronian_area {
|
||
my $hero = hero my ($a, $b, $c) = @_[0,1,2];
|
||
sprintf("%.0f", $hero) eq $hero ? $hero : 0
|
||
}
|
||
|
||
sub primitive_heronian_area {
|
||
my ($a, $b, $c) = @_[0,1,2];
|
||
heronian_area($a, $b, $c) if 1 == gcd $a, gcd $b, $c;
|
||
}
|
||
|
||
sub show {
|
||
print " Area Perimeter Sides\n";
|
||
for (@_) {
|
||
my ($area, $perim, $c, $b, $a) = @$_;
|
||
printf "%7d %9d %d×%d×%d\n", $area, $perim, $a, $b, $c;
|
||
}
|
||
}
|
||
|
||
sub main {
|
||
my $maxside = shift // 200;
|
||
my $first = shift // 10;
|
||
my $witharea = shift // 210;
|
||
my @h;
|
||
for my $c (1 .. $maxside) {
|
||
for my $b (1 .. $c) {
|
||
for my $a ($c - $b + 1 .. $b) {
|
||
if (my $area = primitive_heronian_area $a, $b, $c) {
|
||
push @h, [$area, $a+$b+$c, $c, $b, $a];
|
||
}
|
||
}
|
||
}
|
||
}
|
||
@h = sort {
|
||
$a->[0] <=> $b->[0]
|
||
or
|
||
$a->[1] <=> $b->[1]
|
||
or
|
||
max(@$a[2,3,4]) <=> max(@$b[2,3,4])
|
||
} @h;
|
||
printf "Primitive Heronian triangles with sides up to %d: %d\n",
|
||
$maxside,
|
||
scalar @h;
|
||
print "First:\n";
|
||
show @h[0 .. $first - 1];
|
||
print "Area $witharea:\n";
|
||
show grep { $_->[0] == $witharea } @h;
|
||
|
||
|
||
}
|
||
|
||
&main();
|