素因数根


14

受数字根的启发,数字的素因数根是当您将一个数字的素因数加在一起,然后对所得数字重复该过程时出现的数字,直到您得到一个质数(它本身就是唯一的主要因素,因此是其自己的主要因素根。4的素数因数根为4,为2 * 2 = 2 + 2,这是唯一的大于1的整数的非素数因数根(这是另一种特殊情况,因为它没有素数)。由素因数根形成的OEIS序列为A029908

例如,24的素因数根为:

24=2*2*2*3

2+2+2+3=9=3*3

3+3=6=2*3

2+3=5, and the only prime factor of 5 is 5.  Therefore, the prime factoral root of 24 is 5.  

你的任务:

编写一个程序或函数,以查找输入整数的素因数根。

输入:

通过任何合理的方法输入的整数,介于2和您的语言将支持的最大整数(包括)之间。不允许专门选择最大整数大小过低的语言(并且还会违反此标准漏洞

输出:

整数,输入的素因数根。

测试用例:

4   -> 4
24  -> 5
11  -> 11
250 -> 17

得分:

这是,最低得分(以字节为单位)获胜!


3
您可以添加4测试用例,因为这是一个例外,在测试答案时很容易忘记它?
scottinet

我们必须将1输出为1吗?
我的代名词是monicareinstate '17

@someone根据链接的OEIS序列,应该为1输出0
scottinet 17-10-4

2
@someone挑战国家的投入将至少为2
马丁安德

@someone对不起,待会儿。正如马丁所说,挑战明确指出输入将大于1,因此当输入为1时的行为是不确定的。
狮ry

Answers:



14

Haskell,61个字节

import Data.Numbers.Primes
until=<<((==)=<<)$sum.primeFactors

在线尝试!

说明

until=<<((==)=<<)接受一个函数f并将其应用于输入,x直到达到一个固定点,即f xequals xprimeFactors返回数字素数的列表,sum得出数字列表的总和。

但是等等,为什么 until=<<((==)=<<) 这项工作看起来如此怪异?

如果我们假设f=sum.primeFactors,一个更自然的定义是until(\x->f x==x)f,因为until它带有一个谓词(一个返回布尔值的函数),一个具有相同输入和返回类型(例如Int -> Int)和该类型值的函数,然后将该函数应用于直到谓词满足为止。

until(\x->f x==x)f是一样的until(\x->(==)(f x)x)f,当它认为g (h x) x是一样的(g=<<h)x,我们得到的until(\x->((==)=<<f)x)f转换Eta后,即变为until((==)=<<f)f。但是,如果我们现在把(==)=<<作为应用于功能f,我们可以看到,until(((==)=<<)f)f又是形式的g (h x) x,有g=untilh=((==)=<<)x=f,所以可以重写(until=<<((==)=<<))f。使用$操作者摆脱外括号的,而代以fsum.primeFactors产率从上面的溶液中。


4
=<<((==)=<<)$哇!
完全人类

2
@icrieverytim我添加了一个解释。如果您对这种魔术的工作方式还有其他疑问,请随时在Haskell聊天室中提问。
Laikoni '17

5

外壳,4个字节

ω(Σp

在线尝试!

说明:

ω(   -- apply the following function until the result no longer changes (fixpoint)
  Σ  -- sum
   p -- the list of primefactors


4

Python 2,84个字节

f=lambda n,d=2:n>1and(n%d and f(n,d+1)or d+f(n/d))
i=input()
exec'i=f(i);'*i
print i

在线尝试!


这可能是一个很愚蠢的问题,但是如何f=lambda n,d=2:n>1and(n%d and f(n,d+1)or d+f(n/d))工作?我从未使用Python(主要是Java和C#)进行编程,因此我不确定此函数的结果是什么。此函数会修改输入n并随后返回输入吗,还是类似于布尔值(其中n>1and(n%d and f(n,d+1)or d+f(n/d))0或1或0或n,或其他)?我试图可视化它的端口在Java / C#中的样子,但是我无法做到,因为我通常并不真正理解这样的Python lambda。
凯文·克鲁伊森

1
@KevinCruijssen等效于n>1 ? (n%d!=0 ? f(n, d+1) : d+f(n/d)) : n>1。一般而言x and y等同于x ? y : x。在大多数情况下x and y or z等同x ? y : z于。
ovs

1
@KevinCruijssen Java端口将类似于f=(n,d=2)->n>1?n%d>0?f(n,d+1):d+f(n/d):0
ovs

喔好吧。感谢您的解释,现在更有意义了。我记得x and yx ? y : x在JavaScript以及。谢谢!
凯文·克鲁伊森

4

爪哇8,175个 144 142 141字节

n->{for(int i,t=n,x;;n=t){for(i=2;i<t;t=t%i++<1?0:t);if(t>1|n<5)return n;for(t=0,i=1;i++<n;)for(;n%i<1;n/=i,t+=x)for(x=i;x>9;x/=10)t+=x%10;}}

-1个字节感谢@Nevay

与某些高尔夫球语言中的单字节不同,Java在素数检查,素因数,数字和等方面相当冗长,因此我认为不足200的值还不算太破旧。
仍然有可能通过组合循环而不是对数字总和使用单独的递归方法来打高尔夫球。

说明:

在这里尝试。

n->{                // Method with integer as both parameter and return-type
  for(int i,        //  Index-integer `i`
          t=n,      //  Temp integer `t`, starting at the input `n`
          x;        //  Temp integer `x`
      ;             //  Loop (1) indefinitely
      n=t){         //    After every iteration, replace `n` with the value `t`
    for(i=2;        //   Reset `i` to 2
        i<t;        //   Inner loop (2) from 2 to `t` (exclusive)
        t=t%i++<1?  //    If `t` is divisible by `i`:
           0        //     Set `t` to 0
          :         //    Else:
           t        //     Leave `t` the same
    );              //   End of inner loop (2)
    if(t>1          //   If `t` is not 0 (it means it's a prime),
       |n<5)        //   or if `n` is below 5 (for edge-cases `4` and 'prime' `1`)
      return n;     //    Return `n` as result
    for(t=0,        //   Reset `t` to 0
        i=1;        //   Reset `i` to 1
        i++<n;)     //   Inner loop (3) from 2 to `n` (inclusive)
      for(;n%i<1;   //    Inner loop (4) as long as `n` is divisible by `i`
          n/=i,     //      After every iteration: Divide `n` by `i`,
          t+=x)     //      and increase `t` by `x`
        for(x=i;    //     Reset `x` to `i`
            x>9;    //     Inner loop (5) as long as `x` contains more than 1 digit
            x/=10)  //       After every iteration, remove the trailing digit
          t+=n%10;  //      Increase `t` with the trailing digit of `n`
                    //     End of inner loop (5) (implicit / single-line body)
                    //    End of inner loop (4) (implicit / single-line body)
                    //   End of inner loop (3) (implicit / single-line body)
  }                 //  End of loop (1)
}                   // End of method

6
+1表示费解地写一个解释,好像这是一种高尔夫球语言一样。
我的代名词是monicareinstate '17

@某人谢谢!由于过去曾经有人问过我有关Java答案的解释,所以我一直将它们添加到我的所有答案中。:)
Kevin Cruijssen

i,t=n,x看起来像它属于Python,哈哈
ETHproductions

@ETHproductions呵呵,太可惜了,我仍然必须添加领导int (不同于Python)。;)
Kevin Cruijssen

您可以使用i++<n代替++i<=n
涅瓦


3

视网膜,30字节

{+`(\1|\b11+?\B)+$
$1;$#1$*
;

一元的输入和输出。

在线尝试!(为方便起见,执行十进制/一元转换。)

说明

{+`(\1|\b11+?\B)+$
$1;$#1$*

{指示视网膜的循环,直到全通失败,直到达到固定点修改字符串,即运行整个程序。因此,程序本身将计算出一个将当前值的素数因子相加的步骤。

该阶段本身计算输入的素因数分解。在+类似{,但直到它停止改变串回路只有这个阶段。正则表达式试图1通过重复匹配相同的子字符串(即因数)来匹配的最终运行。由于前向引用,完成此操作的方法有些复杂\1。在第一次迭代中,group 1尚未捕获任何内容,因此\1无条件失败。取而代之的是,我们必须匹配\b11+?\B从运行开始时开始的最小可能的子字符串,该子字符串至少包含两个,即一次又一次地重复相同的子字符串。这个过程必须精确地到达字符串的末尾(1 s并且不覆盖整个运行。由于,后续的迭代将无法再次使用此替代方法\b。因此,在所有其他迭代中,我们都匹配\1$),以确保我们已捕获和实际的除数。使用这种有些棘手的方法的好处是该组1将被精确地使用过n / d次,即除以d后剩下的数

我们替换此匹配与d$1),分离;N / d$#1$*,其中插入物$#1的拷贝1,其中,$#1由小组提出捕获的数目1)。

一旦字符串中的最终运行本身是素数,此过程就会停止,因为正则表达式不再匹配。

;

我们对素数求和所需要做的就是删除所有分隔符。



2

实际上,7个字节

⌠w♂πΣ⌡Y

在线尝试!

说明:

⌠w♂πΣ⌡Y
⌠    ⌡Y  do this until output stops changing (fixed-point combinator)
 w         factor into [prime, exponent] pairs
  ♂π       product of each pair
    Σ      sum of products

2

R + pramma,53个字节

function(n){for(i in 1:n)n=sum(pracma::factors(n))
n}

在线尝试!(小提琴)

R没有一个主要因素,内置的,但无数的包(pracmanumbers,等)做的,所以我选择了一个使用方便的短之一。


1

果冻,6个字节

此答案使用了Jelly的许多素数分解内置函数之一,而使用的是Quick repeat until the results are no longer unique

ÆfSµÐL

在线尝试!


我想你已经outgolfed但是,鉴于你的方法,我不能肯定这个答案的作品
凯尔德coinheringaahing

@cairdcoinheringaahing我刚刚检查了他的答案(或者说,等效于Python)从1到100000,并且它可以正常工作。我认为这1是唯一需要的步骤数等于n(这很好;1我们只需要运行一次)的情况,而且似乎没有任何情况下步骤数大于n(即似乎没有任何反例)。嗯,我已经不高兴了:D
Sherlock9年

好吧,它发生了。虽然+1是我想,当我看到这道难题的完全相同的代码
凯尔德coinheringaahing

n的素数因子之和始终小于或等于n,这很容易证明n总是大于n。
克里斯(Chris)


1

PowerShell,124字节

function f($a){for($i=2;$a-gt1){if(!($a%$i)){$i;$a/=$i}else{$i++}}}
for($x=$args[0];$l-ne$x){$l=$x;$x=(f($x))-join'+'|iex}$x

在线尝试!

PowerShell没有内置的素因分解函数,因此它使用我对“素因好友”(最上面一行)的回答中的代码执行因子分解计算。

第二行是该程序的内容。我们从输入$args$x,然后for循环,直到$l-nOT e资格赛来$x。(第一次迭代$l$null$x是整数,因此我们至少循环一次)。

在循环内部,我们设置$l = $x以确定是否已经到达循环的结尾。然后,我们得到的因素$xf($x)-join与那些一起+|iex他们(简称Invoke-Expression和类似eval)。该内容将存储回$x。因此,我们已经达到了“终点”,其中素因分解加总又回到了自身。然后,我们只需将其放置$x在管道上,并且输出是隐式的。


0

Mathematica,35个字节

#//.x_:>Tr[1##&@@@FactorInteger@x]&

在线尝试!

(数学不支持Tr。我必须手动实现它)


4
1##& is short for Times and FixedPoint can almost always be shortened with //.: #//.x_:>Tr[1##&@@@FactorInteger@x]&
Martin Ender

@MartinEnder Thanks! I should have already known about Times, but I've not known about the FixedPoint trick.
user202729

Your code is written in Mathematica. This is not a Mathics function. You should either change the language name to Mathematica or Tr to Total
J42161217

@{no one} Sorry, language name (Mathics) was a mistake. {i cri evritime} fixed that.
user202729


0

Ruby, 63 bytes

->n{n.times{n=n.prime_division.map{|x|x.reduce:*}.sum};n}

Try it online!

Uses the -rprime flag for +6 bytes to make use of Prime#prime_division.

prime_division返回的对[prime, exponent](例如,对于24个因子[2, 2, 2, 3],我们给出了[[2, 3], [3, 1]]),因此在每一步中,我们只将这些对的成员相乘并求和即可。


0

Javascript(ES6),63个字节

f=n=>(q=(p=(m,x)=>m<x?0:m%x?p(m,x+1):x+p(m/x,x))(n,2))^n?f(q):q
<input id=i type=number min=0 value=0 oninput="o.innerText=f(i.value)">
<p id=o></p>

取消高尔夫:

f=n=>(                  // Recursive function `f`
    p=(m,x=2)=>(        //   Recursive function `p`, used to sum prime factors
        m<x?            //     If m (the number to be factored) is less than x (the current
            0           //     iteration), return 0
        :m%x?           //     Else if m doesn't divide x
            p(m,x+1)    //     run the next iteration
        :               //     Else (if m divides x)
            x+p(m/x,x)  //     Divide m by x and repeat the current iteration
    ),
    q=p(n),             //   Set q to the sum of the prime factors of n
    q^n?                //   If q != n then
        f(q)            //     repeat f with q
    :                   //   else
        q               //     return q
)

0

Java 8,101字节

n->{for(int i=n;i-->0;n=f(n,2));return n;}int f(int n,int d){return n>1?n%d>0?f(n,d+1):d+f(n/d,2):0;}

@ovs惊人的Python 2答案端口。

说明:

在这里尝试。

n->{                  // Method with integer as both parameter and return-type
  for(int i=n;i-->0;  //  Loop the input amount of times
    n=f(n,2)          //   And change `n` that many times with a separate method call
  );                  //  End of loop
  return n;           //  Then return the integer `n` as result
}                     // End of method

int f(int n,int d){   // Separated method with 2 integer parameters and integer return-type
                      // (`d` is 2 when we initially call this recursive-method)
  return n>1?         //  If input `n` is larger than 1:
    n%d>0?            //   And it's not divisible by `d`:
     f(n,d+1)         //    Do a recursive-call with `n, d+1`
    :                 //   Else:
     d                //    Sum `d` with
      +f(n/d,2)       //    a recursive call with `n/d, 2`
   :                  //  Else:
    0;                //   Simply return 0
}                     // End of separated method
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.