[libmath-prime-util-perl] 23/54: Add two more PE examples

Partha P. Mukherjee ppm-guest at moszumanska.debian.org
Thu May 21 18:52:08 UTC 2015


This is an automated email from the git hooks/post-receive script.

ppm-guest pushed a commit to annotated tag v0.38
in repository libmath-prime-util-perl.

commit 684133940c30235ef6d09def31dbab0253725d56
Author: Dana Jacobsen <dana at acm.org>
Date:   Tue Feb 11 17:21:39 2014 -0800

    Add two more PE examples
---
 MANIFEST                      |   2 +
 examples/project_euler_214.pl |  21 +++++++++
 examples/project_euler_342.pl | 100 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 123 insertions(+)

diff --git a/MANIFEST b/MANIFEST
index 2a680d3..5b0e3b1 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -77,6 +77,8 @@ examples/project_euler_069.pl
 examples/project_euler_070.pl
 examples/project_euler_095.pl
 examples/project_euler_211.pl
+examples/project_euler_214.pl
+examples/project_euler_342.pl
 examples/project_euler_357.pl
 bin/primes.pl
 bin/factor.pl
diff --git a/examples/project_euler_214.pl b/examples/project_euler_214.pl
new file mode 100644
index 0000000..720ca6e
--- /dev/null
+++ b/examples/project_euler_214.pl
@@ -0,0 +1,21 @@
+#!/usr/bin/env perl
+use warnings;
+use strict;
+use Math::Prime::Util qw/forprimes euler_phi/;
+
+my $limit = shift || 40000000;
+my $cl = shift || 25;
+
+my @c;
+sub totchainlen {
+  my $n = shift;
+  return $n if $n <= 2;
+  $c[$n] //= 1 + totchainlen(euler_phi($n));
+  return $c[$n];
+}
+
+my $sum = 0;
+forprimes {
+  $sum += $_ if totchainlen($_) == $cl;
+} $limit;
+print "$sum\n";
diff --git a/examples/project_euler_342.pl b/examples/project_euler_342.pl
new file mode 100644
index 0000000..42051f9
--- /dev/null
+++ b/examples/project_euler_342.pl
@@ -0,0 +1,100 @@
+#!/usr/bin/env perl
+use warnings;
+use strict;
+use Math::Prime::Util qw/:all/;
+use Math::GMPz;
+
+# Sum of all n where is_power(euler_phi(n^2),3) = 1
+
+# Simple but very slow way.  The brute force method later in this file is
+# basically the same thing, but using the more efficient ranged moebius and
+# totient calls over intervals.
+#
+#  Pari:
+#    s=0; for(n=2,limit,if(ispower(n*eulerphi(n),3),s=s+n)); print(s)
+#  Perl/MPU:
+#    my $s=0;
+#    for my $n (2..$limit) { $s += $n if is_power($n*euler_phi($n),3); }
+#    say $s;
+#
+# TIMING:
+#              10^7    2*10^7   10^8     10^10
+# Clever       0.07s    0.09s   0.24s    5s
+# Brute        5.8s    11.0s   53.9s     5 hours
+# Simple MPU  13.9s    29.7s  192s       1-2 days?
+# Simple Pari 13.6s    33.4s  277s       5 days?
+#   
+
+my $limit = shift || 10**10-1;
+my $method = lc(shift || 'clever');
+die "Method must be 'clever' or 'brute'\n" unless $method =~ /^(clever|brute)$/;
+my $sum = 0;
+
+
+if ($method eq 'clever') {
+  # About 5 seconds for 10^10-1
+  my $sqlimit = Math::GMPz->new($limit) * $limit;
+  my $cblimit = int( ($limit*$limit) ** 0.3334 + 0.01 );
+  foreach my $k (2 .. $cblimit) {
+    next if $k & 1;
+    my($p, $e) = @{ (factor_exp($k))[-1] };
+    $e *= 3;
+    next unless $e & 1;
+    my $m = int($k / ($p ** int($e/3)));
+    $m **= 3;
+    next if $m % ($p-1);
+    $m = int($m / ($p-1));
+    my $n = $p ** (($e+1) >> 1);
+    next if $n >= $limit;
+    while ($m > 1) {
+      my ($p,$e) = @{ (factor_exp($m))[-1] };
+      last unless $e & 1;
+      last if $m % ($p-1);
+      $n *= $p ** (($e+1) >> 1);
+      last if $n >= $limit;
+      $m = int($m / ( ($p-1) * ($p**$e) ) );
+    }
+    if ($m == 1) {
+      #print "$n\n";
+      $sum += $n;
+    }
+  }
+} else {
+  # About 5 hours for 10^10-1
+  my $interval = 10_000_000;   # Window size for moebius/totient
+  #prime_precalc(10**9);        # Slightly faster ranged phi
+  my($beg,$end) = (0,0);
+  while ($beg < $limit) {
+    $end = $beg + $interval - 1;
+    $end = $limit if $end > $limit;
+    my $start = ($beg<2)?2:$beg;
+
+    my $glim = int(~0 / $end);
+    my @m = moebius($beg, $end);
+    my @t = euler_phi($beg, $end);
+
+    if ($end <= $glim) {   # Totient($n) * $n will always be < ~0
+      foreach my $n ($start .. $end) {
+        next unless $m[$n-$beg] == 0;
+        my $totn2 = $n * $t[$n-$beg];
+        if (is_power($totn2,3)) {
+          # print "$n\n";
+          $sum += $n
+        }
+      }
+    } else {
+      foreach my $n ($start .. $end) {
+        next unless $m[$n-$beg] == 0;
+        my $tot = $t[$n-$beg];
+        if ($tot <= $glim) {
+          print "$n\n" if is_power($n * $tot, 3);
+        } else {
+          $tot = Math::GMPz->new($n) * $tot;
+          print "$n\n" if Math::GMPz::Rmpz_perfect_power_p($tot) && is_power($tot,3);
+        }
+      }
+    }
+    $beg = $end+1;
+  }
+}
+print "$sum\n";

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-perl/packages/libmath-prime-util-perl.git



More information about the Pkg-perl-cvs-commits mailing list