最大の除数を減算することにより、nから1までのステップ数は?


50

数学でこの質問に触発されました


問題

ましょうn自然数≥ 2です。の最大の除数(それ自体nとは異なる)をn取得し、それからを引きnます。になるまで繰り返します1

質問

1特定の数に達するのに何歩かかりますかn ≥ 2

詳細な例

させてくださいn = 30

の最大の除数:

1.   30 is 15  -->  30 - 15 = 15
2.   15 is  5  -->  15 -  5 = 10
3.   10 is  5  -->  10 -  5 =  5
4.    5 is  1  -->   5 -  1 =  4
5.    4 is  2  -->   4 -  2 =  2
6.    2 is  1  -->   2 -  1 =  1

到達するのに6つのステップが必要1です。

入力

  • 入力は整数でn、ここn ≥ 2
  • プログラムは、言語の最大整数値までの入力をサポートする必要があります。

出力

  • のように、単にステップ数を出力します6
  • 先頭または末尾の空白または改行は問題ありません。

f(5)        --> 3
f(30)       --> 6
f(31)       --> 7
f(32)       --> 5
f(100)      --> 8
f(200)      --> 9
f(2016^155) --> 2015

必要条件

  • 入力はSTDIN、コマンドライン引数、関数パラメーターとして、または最も近い同等のものから取得できます。
  • プログラムまたは関数を作成できます。無名関数の場合は、呼び出す方法の例を含めてください。
  • これはので、バイト単位の最短回答が勝ちです。
  • 標準の抜け穴は許可されていません。

このシリーズは、OEISにもあります:A064097

誘導定義された準対数a(1) = 0a(p) = 1 + a(p-1)場合は、pプライムとあるa(n*m) = a(n) + a(m)場合m,n > 1


ネイティブの任意精度整数を持つ言語の入力要件を明確にしますか?
スパー

@Sparr少なくとも、までサポートする必要があり2^32 - 1ます。残りはあなたとあなたのシステム次第です。希望、これがあなたの質問で意味したことです。
ここにユーザー名を挿入

3
タイトルがすべてを要約しているのが好きです
ルイスメンドー

回答:


20

ゼリー、9 バイト

ÆṪÐĿÆFL€S

オンラインでお試しください!または、すべてのテストケースを確認します

バックグラウンド

シーケンスA064097の定義は、

定義

ことでオイラーの製品式

オイラーの積公式

ここで、φはオイラーのトーティエント関数を表し、pは素数でのみ変化します。

両方を組み合わせて、プロパティを推測します

最初の財産

ここで、ωnの異なる素因数の数を示します。

得られた式適用1 + kは時間、kが大きい十分では、そのようφ K + 1(N)= 1、我々 GET

第二の財産

このプロパティから、式を取得します

式

ここで、ω(1)= 0であるため、最後の等式が成り立ちます

使い方

ÆṪÐĿÆFL€S  Main link. Argument: n

  ÐĿ       Repeatedly apply the link to the left until the results are no longer
           unique, and return the list of unique results.
ÆṪ           Apply Euler's totient function.
           Since φ(1) = 1, This computes φ-towers until 1 is reached.
    ÆF     Break each resulting integer into [prime, exponent] pairs.
      L€   Compute the length of each list.
           This counts the number of distinct prime factors.
        S  Add the results.

今、それは非常に賢いアプローチです!
Abr001am

15

05AB1E13 11バイト

コード:

[DÒ¦P-¼D#]¾

説明:

[        ]   # An infinite loop and...
       D#        break out of the loop when the value is equal to 1.
 D           # Duplicate top of the stack (or in the beginning: duplicate input).
  Ò          # Get the prime factors, in the form [2, 3, 5]
   ¦         # Remove the first prime factor (the smallest one), in order to get 
               the largest product.
    P        # Take the product, [3, 5] -> 15, [] -> 1.
     -       # Substract from the current value.
      ¼      # Add one to the counting variable.
          ¾  # Push the counting variable and implicitly print that value.

CP-1252エンコードを使用します。オンラインでお試しください!


13
最大の製品を得るために、最初の素因数(最小のもの)を削除します。:-)
ルイスメンドー

私が見るには、言語の開発者である
Sargeのボルシチ

@SargeBorschはい、それは正しいです:)
アドナン

[¼Ñü-¤ÄD#]¾-私は、近いシェービングにペアごとのバイトオフだったまあいい...
マジックタコ壺

-1バイト:[Ð#Ò¦P-¼]¾Ðよりも優れていDDます。
グリムミー

11

Pyth、11バイト

fq1=-Q/QhPQ

テストスイート

単純なrepeat-until-trueループ。

説明:

fq1=-Q/QhPQ
               Implicit: Q = eval(input())
f              Apply the following function until it is truthy,
               incrementing T each time starting at 1:
         PQ    Take the prime factorization of Q
        h      Take its first element, the smallest factor of Q
      /Q       Divide Q by that, giving Q's largest factor
    -Q         Subtract the result from Q
   =           Assign Q to that value
 q1            Check if Q is now 1.

これは、filterの非常に素晴らしいトリックです。
マルティセン

3
これが関数の実行回数を出力する理由がわかりません。これは文書化されていない機能fですか?
corsiKa

f2番目の引数を指定しない@corsiKa は、すべての正の整数を反復処理し1、最初の値を返します。この値は、内部ステートメントでtrueになります。この値はこのプログラムでは使用されていないため、実行された回数を返します。文書化されていませんが、非正統的です:)それが役立つ場合、次のforようなループと考えることができますfor(int i=1; some_condition_unrelated_to_i; i++) { change_stuff_that_affects_condition_but_not_i;}
。– FryAmTheEggman

@corsiKaオンライン通訳の右側の文字参照に文書化されています。一つだけの引数(とf <l:T> <none>)、fである最初の入力A(_)オーバーtruthyですが[1, 2, 3, 4...]
デニス

ああ、今理解しています。その入力を使用しますが、計算では入力を使用しません。@Maltysenのコメント "これは本当にすごいトリックです"の説明です。なぜなら、フィルター内のどこでもそのカウントを使用しない反復カウントだけに関心があるからです。私はそれらのah-haの瞬間が大好きです!:)
corsiKa

7

Pythonの2、50の 49バイト

f=lambda n,k=1:2/n or n%(n-k)and f(n,k+1)or-~f(k)

これは、その最後のテストケースをすぐには終了しません...

あるいは、forのTrue代わりに返される48バイト1ですn=2

f=lambda n,k=1:n<3or n%(n-k)and f(n,k+1)or-~f(k)

6

ゼリー、10 バイト

ÆfḊPạµÐĿi2

オンラインでお試しください!または、ほとんどのテストケースを確認します。最後のテストケースはローカルですぐに終了します。

使い方

ÆfḊPạµÐĿi2  Main link. Argument: n (integer)

Æf          Factorize n, yielding a list of primes, [] for 1, or [0] for 0.
  Ḋ         Dequeue; remove the first (smallest) element.
   P        Take the product.
            This yields the largest proper divisor if n > 1, 1 if n < 2.
    ạ       Yield the abs. value of the difference of the divisor (or 1) and n.
     µ      Convert the chain to the left into a link.
      ÐĿ    Repeatedly execute the link until the results are no longer unique.
            Collect all intermediate results in a list.
            For each starting value of n, the last results are 2 -> 1 -> 0 (-> 1).
        i2  Compute the 1-based index of 2.

5

網膜、12

  • @MartinBüttnerのおかげで14バイト節約
(1 +)(?= \ 1 + $)

これは、入力が単項で与えられ、出力が10進数で与えられることを前提としています。これが受け入れられない場合は、さらに6バイトでこれを実行できます。

網膜、18

  • @MartinBüttnerのおかげで8バイト節約
。+
$ *
(1 +)(?= \ 1 + $)

オンラインで試してください-すべてのテストケースを一度に実行するために1行目が追加されました。

悲しいことに、これは計算に単項式を使用しているため、2016 155の入力は実用的ではありません。

  • 最初のステージ(2行)は、単に10進数の入力を1sの文字列として単項に変換します
  • 2番目のステージ(1行)は、正規表現マッチンググループと後読みを使用してnの最大係数を計算し、nから効果的に減算します。この正規表現は、可能な限り数を減らすために必要な回数一致します。正規表現の一致数はステップ数になり、この段階で出力されます。

私はあなたが必要とは思わない\b
マーティンエンダー


おはようございます!とてもエレガント-ありがとう!
デジタル外傷

5

Pyth- 15 14 13バイト

特別なケーシング1は本当に私を殺しています。

tl.u-N/Nh+PN2

こちらからオンラインでお試しください

tl                One minus the length of
 .u               Cumulative fixed point operator implicitly on input
  -N              N -
   /N             N /
    h             Smallest prime factor
     +PN2         Prime factorization of lambda var, with two added to work with 1

1
私はいつも忘れることの一つは、....ブルートフォースは、多くの場合、golfiestアプローチである
漏れ修道女

特別なケーシングとはどういう意味1ですか?
アドナン

1
@Adnanの素因数分解は1[]、最初の要素を取得するとエラーが発生します。固定小数点が終了する1ように、再び返すようにするには特別な場合が必要.uです。.xtry-except よりも良い方法を見つけたので、2バイト節約できました。
マルティセン

> = 2(> 1)の数字のみを受け入れる必要があります。
ソロモンウッコ

@SolomonUckoあなたは誤解していますが、.u固定小数点は最終的に1すべての入力に到達しますが、その時点で特別なケースにする必要があります。
マルティセン

5

JavaScript(ES6)、* 44 38

@ l4m2のおかげで6バイトを編集できました

(* 4ストライキはまだ4です)

再帰関数

f=(n,d=n)=>n>1?n%--d?f(n,d):f(n-d)+1:0

少ないゴルフ

f=(n, d=n-1)=>{
  if (n>1)
    if(n % d != 0)
      return f(n, d-1) // same number, try a smaller divisor
    else
      return f(n-d)+1  // reduce number, increment step, repeat
  else
    return 0
}

テスト

f=(n,d=n)=>n>1?n%--d?f(n,d):f(n-d)+1:0

console.log=x=>O.textContent+=x+'\n';

[5,30,31,32,100,200].forEach(x=>console.log(x+' -> '+f(x)))
<pre id=O></pre>


いいですが、f(1)== 0にするために必要な2バイトを費やす必要があると思います
ニール

@ニールが再び考えている:いいえ。「nを2以上の自然数にします...」
edc65

新しいメガネが必要です。
ニール

どうしてf=(n,d=n)=>n>1?n%--d?f(n,d):f(n-d)+1:0
l4m2

@ l4m2右、なぜですか?ありがとう
-edc65

4

Mathematica、36バイト

f@1=0;f@n_:=f[n-Divisors[n][[-2]]]+1

名前のない関数は同じバイトを受け取ります:

If[#<2,0,#0[#-Divisors[#][[-2]]]+1]&

これは、再帰関数としての定義の非常に簡単な実装です。


4

オクターブ、59 58 55バイト

function r=f(x)r=0;while(x-=x/factor(x)(1));r++;end;end

Stewie Griffinのおかげで更新され、1バイト節約

さらに更新し、while-checkで因数分解の結果を使用してさらに3バイトを節約します。

サンプルの実行:

octave:41> f(5)
ans =  3
octave:42> f(30)
ans =  6
octave:43> f(31)
ans =  7
octave:44> f(32)
ans =  5
octave:45> f(100)
ans =  8
octave:46> f(200)
ans =  9

最後endはオクターブ単位で必要ですか?
Abr001am

そうです。私はそれがあなたの答えからmatlabにないことに気付きましたが、Octaveはそれを期待しています(Octaveであなたのものを試してから学んだように)。
dcsohl

4

Haskell、59バイト

f 1=0;f n=1+(f$n-(last$filter(\x->n`mod`x==0)[1..n`div`2]))

使用法:

Prelude> f 30
Prelude> 6

リストを生成するため、大きな数値に対しては少し効率が悪い場合があります。


1
内包表記をリストし、数バイト<1==0節約する代わりに:f 1=0;f n=1+f(n-last[a|a<-[1..ndiv2],mod n a<1])
Angs

4

ジュリア、56 50 45 39バイト

f(n)=n>1&&f(n-n÷first(factor(n))[1])+1

これは、整数を受け入れて整数を返す再帰関数です。

ゴルフをしていない:

function f(n)
    if n < 2
        # No decrementing necessary
        return 0
    else
        # As Dennis showed in his Jelly answer, we don't need to
        # divide by the smallest prime factor; any prime factor
        # will do. Since `factor` returns a `Dict` which isn't
        # sorted, `first` doesn't always get the smallest, and
        # that's okay.
        return f(n - n ÷ first(factor(n))[1]) + 1
    end
end

オンラインでお試しください!(すべてのテストケースを含む)

MartinBüttnerのおかげで6バイト、Dennisのおかげで11バイト節約しました!


3

PowerShell v2 +、81バイト

param($a)for(;$a-gt1){for($i=$a-1;$i-gt0;$i--){if(!($a%$i)){$j++;$a-=$i;$i=0}}}$j

ブルートフォースのブルート。

入力を受け取り$a、以下になるforまでループに入ります。各ループは、除数()が見つかるまでカウントダウンする別のループを通過します。最悪の場合、除数として検出されます。その場合、counterをインクリメントし、除数を減算して、内側のループから抜け出すように設定します。最終的に、外側のループがfalse(つまりに達した)の状態になるため、出力して終了します。$a1for$a!($a%$i$i=1$j$a-=$i$i=0$a1$j

注意:これはかかります長いより多く、特に素数に時間を。Core i5ラップトップでは、100,000,000の入力に約35秒かかります。編集 - [int]::MaxValue(2 ^ 32-1)でテストしたところ、約27分かかりました。ではない、あまりにも悪い、私は考えます。


3

Matlab、58バイト

function p=l(a),p=0;if(a-1),p=1+l(a-a/min(factor(a)));end

3

Japt、12バイト(非競合)

@!(UµUk Å×}a

オンラインでテストしてください!チャレンジが投稿された後に追加された多くの機能を使用するため、競合しません。

使い方

@   !(Uµ Uk Å  ×   }a
XYZ{!(U-=Uk s1 r*1 }a
                       // Implicit: U = input integer
XYZ{               }a  // Return the smallest non-negative integer X which returns
                       // a truthy value when run through this function:
         Uk            //   Take the prime factorization of U.
            s1         //   Slice off the first item.
                       //   Now we have all but the smallest prime factor of U.
               r*1     //   Reduce the result by multiplication, starting at 1.
                       //   This takes the product of the array, which is the
                       //   largest divisor of U.
      U-=              //   Subtract the result from U.
    !(                 //   Return !U (which is basically U == 0).
                       //   Since we started at 0, U == 1 after 1 less iteration than
                       //   the desired result. U == 0 works because the smallest
                       //   divisor of 1 is 1, so the next term after 1 is 0.
                       // Implicit: output result of last expression

この手法は05AB1Eの回答に触発されました。以前のバージョンは、(末尾のスペースに注意してください)より1バイト短いため²¤、代わりに使用しました (最初の2つのアイテムから2つをスライスします)。これは、配列の最後に2を追加し、先頭からスライスするため、特定のすべてのテストケースで機能しますが、実際には奇数の複合数では失敗するという事実に気づいただけです。Ås1 


2

Pythonの3、75、70、67バイト。

g=lambda x,y=0:y*(x<2)or[g(x-z,y+1)for z in range(1,x)if x%z<1][-1]

これは非常に単純な再帰的ソリューションです。多数のテストケースでは、非常に長い時間がかかります。


2

> <>、32バイト

<\?=2:-$@:$/:
1-$:@@:@%?!\
;/ln

nスタック上の入力番号を期待します。

このプログラムは、スタック上に完全なシーケンスを構築します。につながる唯一の数12であるため、シーケンスの構築2はに達すると停止します。これにより、スタックのサイズは、ステップ数+1ではなく、ステップ数と等しくなります。


2

ルビー、43バイト

f=->x{x<2?0:1+f[(1..x).find{|i|x%(x-i)<1}]}

最も小さい番号の検索iようにx分裂をx-iし、私たちが到達するまで再帰1


2

Haskell、67バイト

コードは次のとおりです。

a&b|b<2=0|a==b=1+2&(b-1)|mod b a<1=1+2&(b-div b a)|1<2=(a+1)&b
(2&)

そして、これがHaskellが素晴らしい理由の1つです。

f = (2&)

(-->) :: Eq a => a -> a -> Bool
(-->) = (==)

h=[f(5)        --> 3
  ,f(30)       --> 6
  ,f(31)       --> 7
  ,f(32)       --> 5
  ,f(100)      --> 8
  ,f(200)      --> 9
  ,f(2016^155) --> 2015
  ]

はい、Haskellではに-->相当するように定義できます==


2

Matlab、107バイト

a=input('');b=factor(a-isprime(a));c=log2(a);while(max(b)>1),b=max(factor(max(b)-1));c=c+1;end,disp(fix(c))
  • 競合しない、これは私の最後の提出の反復的な翻訳ではなく、別の直接的な代数的方法であり、すべての素因数のすべてのバイナリログを要約します。
  • 時間があるときにもっとゴルフをします。

2

MATL、17 16バイト

`tttYfl)/-tq]vnq

オンラインで試す

説明

        % Implicitly grab input
`       % Do while loop
    ttt % Make three copies of top stack element
    Yf  % Compute all prime factors
    l)  % Grab the smallest one
    /   % Divide by this to get the biggest divisor
    -   % Subtract the biggest divisor
    t   % Duplicate the result
    q   % Subtract one (causes loop to terminate when the value is 1). This
        % is functionally equivalent to doing 1> (since the input will always be positive) 
        % with fewer bytes
]       % End do...while loop
v       % Vertically concatenate stack contents (consumes entire stack)
n       % Determine length of the result
q       % Subtract 1 from the length
        % Implicitly display result

2

C99、62の 61バイト

@Alchymistによって1バイトがゴルフオフ。

f(a,c,b)long*c,a,b;{for(*c=0,b=a;a^1;a%--b||(++*c,b=a-=b));}  

f(x、&y)として呼び出します。xは入力、yは出力です。


a%-bをテストすると、最後にb--を回避できます。全体で1バイトの節約。
アルキミスト


2

Clojure、116 104バイト

(fn[n](loop[m n t 1](let[s(- m(last(filter #(=(rem m %)0)(range 1 m))))](if(< s 2)t(recur s (inc t))))))

範囲をフィルタリングして倍数を検出し、last1つを使用して最大のものを取得することにより、-12バイト

OPで説明されている問題を基本的に解決する単純なソリューション。残念ながら、最大の除数を見つけるだけでも、使用されるバイトの半分ほどを占有します。少なくともここからゴルフをする余地が十分にあるはずです。

プレゴルフとテスト:

(defn great-divider [n]
  ; Filter a range to find multiples, then take the last one to get the largest
  (last
     (filter #(= (rem n %) 0)
             (range 1 n))))

(defn sub-great-divide [n]
  (loop [m n
         step 1]
    (let [g-d (great-divider m) ; Find greatest divisor of m
          diff (- m g-d)] ; Find the difference
      (println m " is " g-d " --> " m " - " g-d " = " diff)
      (if (< diff 2)
        step
        (recur diff (inc step))))))

(sub-great-divide 30)

30  is  15  -->  30  -  15  =  15
15  is  5  -->  15  -  5  =  10
10  is  5  -->  10  -  5  =  5
5  is  1  -->  5  -  1  =  4
4  is  2  -->  4  -  2  =  2
2  is  1  -->  2  -  1  =  1
6

1
@insertusernamehereいいえ、残念ながら、これらはすべて有効な識別子です。考えられるすべての空白を削除しました。さらにゴルフをしたい場合は、アルゴリズムを作り直す必要があります。
発がん性

2

Perl 6、35バイト

{+({$_ -first $_%%*,[R,] ^$_}...1)}

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

使い方

{                                 }   # A bare block lambda.
                    [R,] ^$_          # Construct range from arg minus 1, down to 0.
        first $_%%*,                  # Get first element that is a divisor of the arg.
    $_ -                              # Subtract it from the arg.
   {                        }...1     # Do this iteratively, until 1 is reached.
 +(                              )    # Return the number of values generated this way.

1

Pyth、17 16バイト

L?tbhy-b*F+1tPb0

オンラインでお試しください!y.v最後は関数呼び出し用です)


元の17バイト:

L?tb+1y-b*F+1tPb0

オンラインでお試しください!y.v最後は関数呼び出し用です)

(私は実際にこの質問にこのPythプログラムで答えました。)


私は実際にあなたのプログラムを気にしませんでしたが、OPで再帰的な定義を使用している場合、uおそらく実際の再帰よりも短いでしょう。
マルティセン

1

Pyke、11バイト(非競合)

D3Phf-oRr;o

これは、gotoの後に例外が発生した場合、gotoの前の状態(変数定義を除く)を復元して続行するという新しい動作を使用します。この場合、次のpythonコードと同等です。

# Implicit input and variable setup
inp = input()
o = 0
# End implicit
try:
    while 1:
        inp -= factors(inp)[0] # If factors is called on the value 1, it returns an empty
                               # list which when the first element tries to be accessed
                               # raises an exception
        o += 1 # Using `o` returns the current value of `o` and increments it
except:
    print o # This in effect gets the number of times the loop went

これは、whileループを作成せずにPykeを使用することで可能です。

ここで試してみてください!


1

JavaScript(ES6)、70 54バイト

f=(n,i=2)=>n<i?0:n%i?f(n,i+1):n>i?f(i)+f(n/i):1+f(n-1)

提供された再帰式の実装。ただし、再帰を使用して除数も見つけるように更新されました。


1

Perl、57 + 1(-pフラグ)= 58バイト

$n=$_;$n-=$n/(grep!($n%$_),2..$n/2,$n)[0],$\++while$n>1}{

使用法:

> echo 31 | perl -pe '$n=$_;$n-=$n/(grep!($n%$_),2..$n/2,$n)[0],$\++while$n>1}{'

ゴルフをしていない:

while (<>) {
# code above added by -p
    # $_ has input value
    # $\ has undef (or 0)
    my $n = $_;
    while ($n > 1) {
        my $d = 1;
        for (2 .. ($n / 2)) {
            if ($n % $_ == 0) {
                $d = $n / $_;
                last;
            }
        }
        $n -= $d;
        $\++;
    }
} {
# code below added by -p
    print;  # prints $_ (undef here) and $\
}

1

Clojure、98 96バイト

#(loop[n % i -1](if n(recur(first(for[j(range(dec n)0 -1):when(=(mod n j)0)](- n j)))(inc i))i))

for :when最大の除数を見つけるために使用し、1より大きい値が見つからなくなるまでループします。

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