在Raku中,如何计算出主要分解的正分裂总和?

发布于 2025-02-12 19:33:49 字数 3558 浏览 1 评论 0原文


在raku中,给定一个对列表(2 => 3,3 => 2,5 => 1,7 => 4)(表示 n的主要因素= 2 3 ·3 2 ·5 1 ·7 4 ),如何为 =(2 0 + 2 1 + 2 2 + 2 3 )·(3 0 + 3 1 + 3 2 2 )·( 5 0 + 5 1 )·(7 0 + 7 1 + 7 2 + 7 3 + 7 4 )?

sub MAIN()
  {
  my $pairList = (2 => 3, 3 => 2, 5 => 1, 7 => 4) ;
  say '$pairList' ;
  say $pairList ;
  say $pairList.WHAT ;
  # Goal:
  #   from $pairList,
  #   the product (1 + 2 + 4 + 8) * (1 + 3 + 9) * (1 + 5) * (1 + 7 + 49 + 343 + 2401)
  #   = sigma ( 2^3 * 3^2 * 5^1 * 7^4 )
  } # end sub MAIN

根据@raiph的答案,更新1

,以下程序将整个过程分为新来的Raku(例如我)……

sub MAIN()
  {
  my $pairList = (2 => 3, 3 => 2, 5 => 1, 7 => 4) ;
  say '$pairList' ;
  say $pairList ;
  say $pairList.WHAT ;

  # Goal:
  #   from $pairList,
  #   the product (1 + 2 + 4 + 8) * (1 + 3 + 9) * (1 + 5) * (1 + 7 + 49 + 343 + 2401)
  #   the product (15) * (13) * (6) * (2801)
  #   sigma ( 2^3 * 3^2 * 5^1 * 7^4 )
  #   3277170

  # Stage 1 : ((1 2 4 8) (1 3 9) (1 5) (1 7 49 343 2401))
  my $stage1 = $pairList.map: { (.key ** (my $++)) xx (.value + 1) } ;
  say '$stage1 : lists of powers' ;
  say $stage1 ;
  say $stage1.WHAT ;

  # Stage 2 : ((1 + 2 + 4 + 8) (1 + 3 + 9) (1 + 5) (1 + 7 + 49 + 343 + 2401))
  my $stage2 = $stage1.map: { sum $_ } ;
  say '$stage2 : sum each list' ;
  say $stage2 ;
  say $stage2.WHAT ;

  # Stage 3 : (1 + 2 + 4 + 8) * (1 + 3 + 9) * (1 + 5) * (1 + 7 + 49 + 343 + 2401)
  my $stage3 = $stage2.reduce( &infix:<*> ) ;
  say '$stage3 : product of list elements' ;
  say $stage3 ;
  say $stage3.WHAT ;
  } # end sub MAIN

相关帖子出现在 数学”堆栈交换


更新2

我最初的动机是计算 > s(n)=σ(n)-n 。我发现每个 n 的主要分解不是必需的,而且似乎效率低下。 raku和c ++程序计算 s(n) for n = 0…10 6 关注…

raku
sub MAIN()
  {
  constant $limit = 1_000_000 ;

  my @s of Int = ( 1 xx ($limit + 1) ) ;
  @s[0] = 0 ;
  @s[1] = 0 ;

  loop ( my $column = 2; $column <= ($limit + 1) div 2; $column++ )
    {
    loop ( my $row = (2 * $column); $row <= $limit; $row += $column )
      {
      @s[$row] += $column ;
      } # end loop $row
    } # end loop $column

  say "s(", $limit, ") = ", @s[$limit] ; # s(1000000) = 1480437
  } # end sub MAIN
c ++
(观察到比Raku的执行速度要快得多)
#include <iostream>
#include <vector>
using namespace std ;

int main ( void )
  {
  const int LIMIT = 1000000 ;
  vector<int> s ( (LIMIT + 1), 1 ) ;
  s[0] = 0 ;
  s[1] = 0 ;
  for ( int col = 2 ; col <= (LIMIT + 1) / 2 ; col++ )
    for ( int row = (2 * col) ; row <= LIMIT ; row += col )
      s[row] += col ;
  cout << "s(" << LIMIT << ") = " << s[LIMIT] << endl ; // s(1000000) = 1480437
  } // end function main



In Raku, given a list of pairs (2 => 3, 3 => 2, 5 => 1, 7 => 4) ( representing the prime factorization of n = 2 3 · 3 2 · 5 1 · 7 4 ), how does construct a Raku expression for σ(n) = ( 2 0 + 2 1 + 2 2 + 2 3 ) · ( 3 0 + 3 1 + 3 2 ) · ( 5 0 + 5 1 ) · ( 7 0 + 7 1 + 7 2 + 7 3 + 7 4 ) ?

sub MAIN()
  {
  my $pairList = (2 => 3, 3 => 2, 5 => 1, 7 => 4) ;
  say '$pairList' ;
  say $pairList ;
  say $pairList.WHAT ;
  # Goal:
  #   from $pairList,
  #   the product (1 + 2 + 4 + 8) * (1 + 3 + 9) * (1 + 5) * (1 + 7 + 49 + 343 + 2401)
  #   = sigma ( 2^3 * 3^2 * 5^1 * 7^4 )
  } # end sub MAIN

Update 1

Based upon the answer of @raiph, the following program breaks the overall process into stages for the newcomer to Raku (such as me) …

sub MAIN()
  {
  my $pairList = (2 => 3, 3 => 2, 5 => 1, 7 => 4) ;
  say '$pairList' ;
  say $pairList ;
  say $pairList.WHAT ;

  # Goal:
  #   from $pairList,
  #   the product (1 + 2 + 4 + 8) * (1 + 3 + 9) * (1 + 5) * (1 + 7 + 49 + 343 + 2401)
  #   the product (15) * (13) * (6) * (2801)
  #   sigma ( 2^3 * 3^2 * 5^1 * 7^4 )
  #   3277170

  # Stage 1 : ((1 2 4 8) (1 3 9) (1 5) (1 7 49 343 2401))
  my $stage1 = $pairList.map: { (.key ** (my $++)) xx (.value + 1) } ;
  say '$stage1 : lists of powers' ;
  say $stage1 ;
  say $stage1.WHAT ;

  # Stage 2 : ((1 + 2 + 4 + 8) (1 + 3 + 9) (1 + 5) (1 + 7 + 49 + 343 + 2401))
  my $stage2 = $stage1.map: { sum $_ } ;
  say '$stage2 : sum each list' ;
  say $stage2 ;
  say $stage2.WHAT ;

  # Stage 3 : (1 + 2 + 4 + 8) * (1 + 3 + 9) * (1 + 5) * (1 + 7 + 49 + 343 + 2401)
  my $stage3 = $stage2.reduce( &infix:<*> ) ;
  say '$stage3 : product of list elements' ;
  say $stage3 ;
  say $stage3.WHAT ;
  } # end sub MAIN

A related post appears on Mathematics Stack Exchange.


Update 2

My original motivation had been to calculate aliquot sum s(n) = σ(n) - n. I found that prime factorization of each n is not necessary and seems inefficient. Raku and C++ programs calculating s(n) for n = 0 … 10 6 follow …

Raku
sub MAIN()
  {
  constant $limit = 1_000_000 ;

  my @s of Int = ( 1 xx ($limit + 1) ) ;
  @s[0] = 0 ;
  @s[1] = 0 ;

  loop ( my $column = 2; $column <= ($limit + 1) div 2; $column++ )
    {
    loop ( my $row = (2 * $column); $row <= $limit; $row += $column )
      {
      @s[$row] += $column ;
      } # end loop $row
    } # end loop $column

  say "s(", $limit, ") = ", @s[$limit] ; # s(1000000) = 1480437
  } # end sub MAIN
C++
(Observed to execute significantly faster than Raku)
#include <iostream>
#include <vector>
using namespace std ;

int main ( void )
  {
  const int LIMIT = 1000000 ;
  vector<int> s ( (LIMIT + 1), 1 ) ;
  s[0] = 0 ;
  s[1] = 0 ;
  for ( int col = 2 ; col <= (LIMIT + 1) / 2 ; col++ )
    for ( int row = (2 * col) ; row <= LIMIT ; row += col )
      s[row] += col ;
  cout << "s(" << LIMIT << ") = " << s[LIMIT] << endl ; // s(1000000) = 1480437
  } // end function main


如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

看透却不说透 2025-02-19 19:33:49

有数十亿美元的方式。我忽略了算法效率。我写的第一件事:

say [*] (2 => 3, 3 => 2, 5 => 1, 7 => 4) .map: { sum .key ** my $++ xx .value + 1 }

显示:

3277170

解释

 1 say
 2  [*]                       # `[op]` is a reduction. `[*] 6, 8, 9` is `432`.
 3    (2 => 3, 3 => 2, 5 => 1, 7 => 4)
 4      .map:
 5        {
 6          sum
 7            .key            # `.key` of `2 => 3` is `2`.
 8              **
 9                my          # `my` resets `

有数十亿美元的方式。我忽略了算法效率。我写的第一件事:

say [*] (2 => 3, 3 => 2, 5 => 1, 7 => 4) .map: { sum .key ** my $++ xx .value + 1 }

显示:

3277170

解释

for each call of enclosing `{...}` 10 $++ # `$++` integer increments from `0` per thunk evaluation. 11 xx # `L xx R` forms list from `L` thunk evaluated `R` times 12 .value + 1 13 }

There'll be bazillions of ways. I've ignored algorithmic efficiency. The first thing I wrote:

say [*] (2 => 3, 3 => 2, 5 => 1, 7 => 4) .map: { sum .key ** my $++ xx .value + 1 }

displays:

3277170

Explanation

 1 say
 2  [*]                       # `[op]` is a reduction. `[*] 6, 8, 9` is `432`.
 3    (2 => 3, 3 => 2, 5 => 1, 7 => 4)
 4      .map:
 5        {
 6          sum
 7            .key            # `.key` of `2 => 3` is `2`.
 8              **
 9                my          # `my` resets `

There'll be bazillions of ways. I've ignored algorithmic efficiency. The first thing I wrote:

say [*] (2 => 3, 3 => 2, 5 => 1, 7 => 4) .map: { sum .key ** my $++ xx .value + 1 }

displays:

3277170

Explanation

for each call of enclosing `{...}` 10 $++ # `$++` integer increments from `0` per thunk evaluation. 11 xx # `L xx R` forms list from `L` thunk evaluated `R` times 12 .value + 1 13 }
薄凉少年不暖心 2025-02-19 19:33:49

对于这种操作,Raku不太可能比C ++更快。它仍然是生命的早期,并且有很多优化的优化,但是原始处理速度并不是它发光的地方。

如果您试图在连续范围内找到所有数字的等分试样总和,那么质量分解肯定不如您所获得的方法效率。有点像eratosthenes的反向筛。您可以更改一些事情以使其更快,尽管

在我的系统上的速度可能比C ++慢得多:

constant $limit = 1_000_000;

my @s = 0,0;
@s.append: 1 xx $limit;

(2 .. $limit/2).race.map: -> $column {
    loop ( my $row = (2 * $column); $row <= $limit; $row += $column ) {
       @s[$row] += $column ;
    }
}

say "s(", $limit, ") = ", @s[$limit] ; # s(1000000) = 1480437

质量分解方法真正发光的是找到 nutyary nutyary 等分的总和。

当反向筛子可能需要几个小时时,这会在一秒钟内产生答案。使用 prime :: factor module :来自raku生态系统

use Prime::Factor;
say "s(", 2**97-1, ") = ", (2**97-1).&proper-divisors.sum;
# s(158456325028528675187087900671) = 13842607235828485645777841

It is unlikely that Raku is ever going to be faster than C++ for that kind of operation. It is still early in its life and there are lots of optimizations to be gained, but raw processing speed is not where it shines.

If you are trying to find the aliquot sum for all of the numbers in a continuous range then prime factorization is certainly less efficient than the method you arrived at. Sort of an inverse Sieve of Eratosthenes. There are a few things you could change to make it faster, though still probably much slower than C++

About twice as fast on my system:

constant $limit = 1_000_000;

my @s = 0,0;
@s.append: 1 xx $limit;

(2 .. $limit/2).race.map: -> $column {
    loop ( my $row = (2 * $column); $row <= $limit; $row += $column ) {
       @s[$row] += $column ;
    }
}

say "s(", $limit, ") = ", @s[$limit] ; # s(1000000) = 1480437

Where the prime factorization method really shines is for finding arbitrary aliquot sums.

This produces an answer in fractions of a second when the inverse sieve would likely take hours. Using the Prime::Factor module: from the Raku ecosystem

use Prime::Factor;
say "s(", 2**97-1, ") = ", (2**97-1).&proper-divisors.sum;
# s(158456325028528675187087900671) = 13842607235828485645777841
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文