use warnings;
use strict;
my $max = int($ARGV[0]) or die "Usage: $0 <max positive integer>\n";
my @divisors;
my %amicable;
for my $n (1 .. $max) {
# 1 is always a divider of any integer
push @{$divisors[$n]}, 1;
# find the rest of the dividers
for (2 .. $max) {
push @{$divisors[$n]}, $_ unless ($n % $_);
}
# check to see if this is a perfect number
my $total = unpack "%123d*" , pack( "d*", @{$divisors[$n]});
print "$n is a perfect number\n" if (2*$n == $total);
# check to see if this is an amicable pair with an earlier number
$amicable{$n} = $total-$n;
if (
exists($amicable{$total-$n}) &&
($amicable{$total-$n} == $n) &&
($n != $total-$n)
)
{
print "$n and " . ($total-$n) . " are an amicable pair\n";
}
}