I made my own attempt at a solution (attached).
It runs in 6s in a Dell Inspiron N5110 and in 53s in an ASUS
Transformer tablet. So I guess it is fast. It seems correct but I have
some doubts (below)

------------------------------ Code:

#!/usr/bin/env perl
use strict;
use warnings;
use feature 'say';
use POSIX 'floor';
use PDL::Lite;
use PDL::NiceSlice;

my $num=$ARGV[0];
my $max=floor(sqrt($num));
my $possible=PDL->sequence($max+1);
$possible->((1)).=0;
foreach(2..$max/2) {
    next unless $possible->(($_));
    $possible->(2*$_:-1:$_).=0;
}
my $primes=$possible->where($possible);
my $factors;
my $allfactors=PDL->zeros(0);

my $n=$num;
do {
    $factors=$primes->where($n%$primes==0);
    $n/=$factors->prod;
    $allfactors=$allfactors->append($factors);
} while $factors->nelem;
$allfactors=$allfactors->append($n) unless $n==1;
say $allfactors->qsort;

Output: -----------------------------------------

mochan@yapaque:~/txt/cache/15/scratch$ time ./erastotenes.pl 600851475143
[71 839 1471 6857]

real    0m6.148s
user    0m6.132s
sys     0m0.012s

----------------------------------------

The do loop is to catch the multiplicity of the prime factors.

There is something strange though. I suspect my system has errors when
calculating moduli, as the factor 71 was the last found instead of
being the first. When I ran with the debugger I got this strange
result:

  DB<9> p $primes->slice('(19)') #get the suspect prime position
71 
  DB<10> p $num%71         #71 divides $num, 600851475143
0
  DB<11> p $num%$primes->slice('(19)') 
753322814151
I expected to obtain zero here, as $primes->slice('(19)')==71, but
instead I obtained 753322814151. So it seems that pdl and perl yield
different results! Could it be due to using default types?

Best regards,
Luis


On Sun, Feb 15, 2015 at 04:03:45PM -0500, Chris Marshall wrote:
> Yes, maybe some use of ->sever to turn off data flow
> might allow things to be freed.  It is definitely
> possible to tend the memory directly in the implementation
> to work around the alloc/free issue.
> 
> --Chris
> 
> On 2/15/2015 08:32, Vikas N Kumar wrote:
> 
>     Chris, this blows up the memory on my Macbook Air and fills up all the 
> swap
>     space (clearly there isn't much) and i had to restart the system to 
> recover
>     it.
>     The pure perl version is more efficient due to possible perl 
> optimizations.
> 
>     So the culprit is the "$possible = where $possible, $possible % $p; " 
> line.
>     There are way too many PDL objects being created and none of them being
>     freed.
> 
>     Here is a more efficient C-based solution that I thought of:
>     I was thinking of a way to store the integers in a bitmap stream of bytes
>     where the integer value is just an index into a bitmap of 0's and 1's.
> 
>     When the integer is composite or divisible by anything other than itself,
>     it's bit can be flipped to 0. So in the end all the primes will be all the
>     bits that are 1, whose indexes can then be collected.
> 
>     I am not sure if I can do this in PDL.
> 
>     It isn't necessary to.
>     Thanks for your program.
> 
>     --Vikas
> 
>     On 02/14/2015 05:27 PM, Chris Marshall wrote:
> 
>         Here is a PDL implementation but it runs in about 5mins
>         on my cygwin/win7 system and uses a lot of memory.  The
>         real performance killer for PDL is the allocation and
>         creation of new PDLs.  The computations are much faster
>         then the plain perl ones.  How does this run on your Mac?
> 
> 
>             #!/usr/bin/env perl
>             use strict;
>             use warnings;
> 
>             use PDL;
>             use PDL::NiceSlice;
> 
>             # use POSIX qw(floor);
>             # Problem 3:
>             # The prime factors of 13195 are 5, 7, 13, 29.
>             # What is the largest prime factor of 600851475143 ?
> 
>             my $num = 600851475143;
>             #my $num = 13195;
> 
>             my $m = floor(sqrt($num));
>             print "max factor limit: $m\n";
> 
>             # solve using sieve of erastothenes
>             my @primes = ();
>             my $possible = indx(2 .. $m);
> 
>             my $cnt = 0;
>             while (any $possible) {
>                my $p = $possible((0));
>                $possible = where $possible, $possible % $p;
>                push @primes, $p;
>                #print "Remaining: ", $possible->nelem, "\n";
>                #print "Found possible prime factor: $p\n";
>             }
> 
>             my $factors = indx(@primes);
>             $factors = where $factors, $num%$factors==0;
>             if (any $factors) {
>                print "Prime Factors of $num: $factors\n";
>             } else {
>                print "$num is prime\n";
>             }
> 
> 
>         Cheers,
>         Chris
> 
>         On 2/14/2015 13:27, Vikas N Kumar wrote:
> 
>             Hi
> 
>             I am just casually solving some Project Euler problems using Perl.
> 
>             For problem 3 (https://projecteuler.net/problem=3) I solved it
>             using the code below. The problem is stated in the code comments.
> 
>             The code is single threaded and takes about 5-10 minutes on a
>             standard Intel i5 CPU on a 3 year old Macbook Air.
> 
>             Can PDL make this faster ? No bignums are being used.
> 
> 
>                 #!/usr/bin/env perl
>                 use strict;
>                 use warnings;
>                 use POSIX qw(floor);
>                 # Problem 3:
>                 # The prime factors of 13195 are 5, 7, 13, 29.
>                 # What is the largest prime factor of 600851475143 ?
>                 my $num = 600851475143;
> 
>                 my $m = floor(sqrt($num));
>                 print "max factor limit: $m\n";
>                 # solve using sieve of erastothenes
>                 #
>                 my @primes = ();
>                 my @possible = (2 .. $m);
>                 while (@possible) {
>                     my $p = shift @possible;
>                     @possible = grep { $_ % $p != 0 } @possible;
>                     push @primes, $p;
>                     print "Remaining: ", scalar(@possible), "\n";
>                     print "Found possible prime factor: $p\n";
>                 }
>                 my @factors = grep { $num % $_ == 0 } @primes;
>                 if (@factors) {
>                     print "Prime Factors of $num: ", join(",", @factors), 
> "\n";
>                 } else {
>                     print "$num is prime\n";
>                 }
> 
> 
> 
> 

> _______________________________________________
> Perldl mailing list
> [email protected]
> http://mailman.jach.hawaii.edu/mailman/listinfo/perldl


-- 

                                                                  o
W. Luis Mochán,                      | tel:(52)(777)329-1734     /<(*)
Instituto de Ciencias Físicas, UNAM  | fax:(52)(777)317-5388     `>/   /\
Apdo. Postal 48-3, 62251             |                           (*)/\/  \
Cuernavaca, Morelos, México          | [email protected]   /\_/\__/
Consider using GnuPrivacyGuard https://www.gnupg.org/
My key: 791EB9EB, C949 3F81 6D9B 1191 9A16  C2DF 5F0A C52B 791E B9EB, yours?




_______________________________________________
Perldl mailing list
[email protected]
http://mailman.jach.hawaii.edu/mailman/listinfo/perldl

Reply via email to