Skip to content

Instantly share code, notes, and snippets.

@adamcrussell
Created May 19, 2019 03:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adamcrussell/b48546dd78ff1dcf5e4c0f426d567881 to your computer and use it in GitHub Desktop.
Save adamcrussell/b48546dd78ff1dcf5e4c0f426d567881 to your computer and use it in GitHub Desktop.
Computing Perfect Numbers with Threads
use strict;
use warnings;
##
# Write a script that computes the first five perfect numbers.
# A perfect number is an integer that is the sum of its positive
# proper divisors (all divisors except itself).
##
use Thread;
use constant THREAD_COUNT => 4;
use constant PERFECT_COUNT => 5;
use constant RANGE_SIZE => 100_000;
sub factor{
my($n) = @_;
my @factors = (1);
foreach my $j (2..sqrt($n)){
push @factors, $j if $n % $j == 0;
push @factors, ($n / $j) if $n % $j == 0 && $j ** 2 != $n;
}
return @factors;
}
sub is_perfect{
my @numbers = @_;
my @perfects = ();
foreach my $n (@numbers){
my @factors = factor($n);
my $sum = unpack("%32I*", pack("I*", @factors));
if($sum == $n){
push @perfects, $n;
}
}
return \@perfects;
}
##
# Main
##
my @threads;
my $count = 0;
my $lower = 2;
my $upper = RANGE_SIZE;
do{
for(0..(THREAD_COUNT - 1)){
my $t = Thread->new(\&is_perfect, ($lower..$upper));
push @threads, $t;
$lower = $upper + 1;
$upper = $lower + RANGE_SIZE;
}
foreach my $t (@threads){
my $perfects = $t->join();
foreach my $p (@{$perfects}){
print "$p ";
$count++;
}
}
@threads = ();
}while($count < PERFECT_COUNT);
print "\n";
use strict;
use warnings;
##
# Write a script that computes the first five perfect numbers.
# A perfect number is an integer that is the sum of its positive
# proper divisors (all divisors except itself).
##
use Thread;
use Perfect;
use constant THREAD_COUNT => 4;
use constant PERFECT_COUNT => 5;
use constant RANGE_SIZE => 100_000;
my $p = new Perfect::Perfect();
sub is_perfect{
my @numbers = @_;
my @perfects = ();
foreach my $n (@numbers){
if($p->isPerfect($n)){
push @perfects, $n;
}
}
return \@perfects;
}
##
# Main
##
my @threads;
my $count = 0;
my $lower = 2;
my $upper = RANGE_SIZE;
do{
for(0..(THREAD_COUNT - 1)){
my $t = Thread->new(\&is_perfect, ($lower..$upper));
push @threads, $t;
$lower = $upper + 1;
$upper = $lower + RANGE_SIZE;
}
foreach my $t (@threads){
my $perfects = $t->join();
foreach my $p (@{$perfects}){
print "$p ";
$count++;
}
}
@threads = ();
}while($count < PERFECT_COUNT);
print "\n";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment