素因数分解の根


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 2017年

1に対して1を出力する必要がありますか?
私の代名詞はmonicareinstateで、2017年

リンクされたOEISシーケンスに従って@ someone、1に対して0を出力する必要があります
scottinet

2
入力は、少なくとも2になることを@someone挑戦状態
マーティン・エンダー

@someoneしばらくお疲れ様でした。マーティンが言ったように、課題は入力が1より大きいと明確に述べているため、入力が1の場合の動作は定義されていません。
グリフォン2017年

回答:


15

05AB1E、3バイト

FÒO

オンラインでお試しください!

説明:

FÒO   
F    Loops <input> times + 1
 Ò   List of prime factors w/ duplicates
  O  Total sum of the list
     -- implicit output

これは失敗するようです4
Shaggy

1
@Shaggyは2バイトの保存中に修正
scottinet

10
これで、これを倒そうとしている人がF beatO戦闘機になりますか?
steenbergh 2017年

少なくともFOObarではありませんでした。
Magic Octopus Urn

14

Haskell、61バイト

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

オンラインでお試しください!

説明

until=<<((==)=<<)関数fを受け取りx、固定点に到達するまで、つまり、にf x等しくなるように入力に適用しますxprimeFactors数値の素因数のリストを返し、sum数値のリストの合計を生成します。

しかし、待ってください、なぜ until=<<((==)=<<) 仕事がとても奇妙に見えるのですか?

と仮定するとf=sum.primeFactors、述語(ブール値を返す関数)、同じ入力と戻り値の型(例:)とこの型の値を持つ関数を取り、関数をに適用するuntil(\x->f x==x)fため、より自然な定義はになります。述語が満たされるまでの値。untilInt -> 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ます。イータ変換後、これはになりuntil((==)=<<f)fます。私たちは今扱う場合でも、(==)=<<に適用される機能としてf、我々はそれを見ることができるuntil(((==)=<<)f)f形式で再びあるg (h x) xと、g=untilh=((==)=<<)そしてx=fそれが書き換えることができるので、(until=<<((==)=<<))f$演算子を使用して外側の括弧を取り除き、で置き換えるfsum.primeFactors、上からの解が得られます。


4
=<<((==)=<<)$うわぁぁぁぁ
完全に人間的な2017年

2
@icrieverytim説明を追加しました。この魔術の仕組みについてさらに質問がある場合は、Haskellチャットルームでお気軽にご質問ください。
ライコニ2017年



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ラムダを実際に理解していないため、視覚化できません。
Kevin Cruijssen、2017年

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

ああ。説明してくれてありがとう、今ではもっと理にかなっています。そして、私もJavaScriptから来たことを覚えx and yx ? y : xいます。ありがとう!
Kevin Cruijssen、2017年

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;}}

@Nevayのおかげで-1バイト。

一部のゴルフ言語の1バイトとは異なり、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で、2017年

@someoneありがとう!誰かが私のJava回答の説明について過去に一度尋ねたので、私はすべての私の回答にそれらを追加しています。:)
Kevin Cruijssen、2017年

i,t=n,xPythonに属しているようです、
ハハ

@ETHproductions Hehe、残念int ですが(Pythonとは異なり)まだ先頭を追加する必要があります。;)
Kevin Cruijssen 2017年

i++<n代わりに使用できます++i<=n
ネベイ


3

Retina、30バイト

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

単項での入力と出力。

オンラインでお試しください!(便宜上、10進/単項変換を実行します。)

説明

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

{、完全なパスが文字列の変更に失敗するまで、つまり固定小数点に達するまで、プログラム全体をループで実行するようRetinaに指示します。その結果、プログラム自体が現在の値の素因数を合計する1つのステップを計算します。

このステージ自体が入力の素因数分解を計算します。+似て{いますが、文字列を変更停止するまで、これだけのステージをループします。正規表現は1、同じ部分文字列(つまり、因子)を繰り返し照合することにより、sの最後の実行との照合を試みます。これが行われる方法は、前方参照のために少し複雑\1です。最初の反復では、グループ1はまだ何もキャプチャしていないため、\1無条件に失敗します。代わりに、\b11+?\B実行の開始点から始まり、少なくとも2つ1のを含み、実行全体をカバーしない、可能な最小のサブストリングである一致する必要があります。のため、後続の反復ではこの代替案を再び使用できません\b。したがって、以降のすべての反復では、\1つまり、同じ部分文字列を何度も繰り返します。このプロセスでは、文字列の最後を正確に($)ヒットして、実際の除数を確実に取得する必要があります。このややトリッキーなアプローチを使用する利点は、グループ1が正確にn / d回使用されることです。つまり、除数dを除算した後に残ったものです。

このマッチをd$1)、分離;およびn / d(は$#1$*、の$#1コピーを挿入します。1ここで、$#1はグループによって行われたキャプチャの数)に置き換え1ます。

文字列の最後の実行自体が素数になると、このプロセスは停止します。これは、正規表現が一致しなくなったためです。

;

素数を合計するために必要なのは、すべてのセパレーターを削除することだけです。





1

ゼリー、6バイト

この答えは、Jellyの多くの素因数分解組み込み関数の1つと、のクイックを使用していrepeat until the results are no longer uniqueます。

ÆfSµÐL

オンラインでお試しください!


私はあなたが外に出たと思いますが、あなたのアプローチを考えると、その答えがうまくいくかどうかはわかりません
caird coinheringaahing

@cairdcoinheringaahing私は彼の答え(または、Pythonの同等のもの)を1から100000までチェックしたところ、うまくいきました。1必要なステップ数が等しいn(これは問題1ありません。一度実行するだけでよい)唯一のケースだと思います。ステップ数がn(つまり反例はないようです)。ああ、私は外に出ました:D
Sherlock9

まあ、それは起こります。私はこの挑戦を見たときに考える、まったく同じコードであるための1が、
caird coinheringaahing

nの素因数の合計は常にn以下であるため、nが常に十分であることを簡単に証明できます。
Chris

1

MATL、6バイト

必要以上にループするというスコティネットのアイデアを使用しています。間違いを指摘してくれたShaggyにも感謝します。

t:"Yfs

オンラインでお試しください!

説明

t       % Take input (implicit). Duplicate
:"      % Do the following that many times
  Yf    %   Array of prime factors
  s     %   Sum of array
        % End (implicit). Display (implicit)

これは失敗するようです4
シャギー

@シャギーありがとう!その作業
Luis Mendo

@Shaggy Solved now
Luis Mendo

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には素因数分解が組み込まれていないため、これは素因数仲間上の行)に関する私の回答のコードを使用して、因数分解計算を実行します。

2行目はこのプログラムの要です。$argsinto から入力を受け取り$x、がに等しくなるforまでループします。(最初の反復はであり、整数なので、少なくとも1回はループします)。$l-ne$x$l$null$x

ループ内では、ループ$l = $xの終わりに到達したかどうかを判断するように設定します。その後、我々はの要因を取得$xしてf($x)-join一緒にそれらを+し、|iexそれら(略しInvoke-Expressionとに類似eval)。それはに保存され$xます。したがって、一緒に合計された素因数分解がそれ自体に戻る「終わり」に到達しました。次に、$xパイプラインに配置するだけで、出力は暗黙的に行われます。


0

Mathematica、35バイト

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

オンラインでお試しください!

(MathicsはをサポートしていませんTr。手動で実装する必要があります)


4
1##&略であるTimesFixedPoint、ほとんどの場合に短縮することができます//.#//.x_:>Tr[1##&@@@FactorInteger@x]&
マーティン・エンダー

@MartinEnderありがとう!私はすでにについて知っているべきTimesでしたが、FixedPointトリックについては知りませんでした。
user202729 2017年

コードはMathematicaで書かれています。これは数学関数ではありません。言語名をMathematicaに変更するか、TrをTotalに変更する必要があります
J42161217

@ {いいえ}申し訳ありませんが、言語名(数学)は誤りでした。{i cri evritime}が修正しました。
user202729 2017年


0

Ruby、63バイト

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

オンラインでお試しください!

-rprime+6バイトのフラグを使用して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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.