N個の除数を持つ最小数を与える


17

関数は自然数を取り、それ自体を含む正確にその数の除数を持つ最小の自然数を返します。

例:

f(1) =  1 [1]
f(2) =  2 [1, 2]
f(3) =  4 [1, 2, 4]
f(4) =  6 [1, 2, 3, 6]
f(5) = 16 [1, 2, 4, 8, 16]
f(6) = 12 [1, 2, 3, 4, 6, 12]
 ...

この関数は除数のリストを返す必要はありません。それらは例のためだけにあります。


2
これはコードゴルフですか、それともコードチャレンジですか?
マリヌス

おっと、そのタグを忘れてしまった、コードゴルフ!
SteeveDroz

回答:


6

APL、25 24 23文字

f←{({+/⍵=⍵∧⍳⍵}¨⍳2*⍵)⍳⍵}

f数値の計算に使用できる関数を定義します。

> f 13
4096

> f 14
192

ソリューションは、xがnを除算する場合、LCM(n、x)== nという事実を利用します。したがって、ブロック{+/⍵=⍵∧⍳⍵}は除数の数を単純に計算します。この関数は1から2 ^ d までのすべての数値に適用されます¨⍳2*⍵。次に、結果のリストからd自体(⍳⍵)が検索されます。これは、目的の関数f(d)です。


おめでとうございます!23文字...すごい!
-SteeveDroz

19:{⍵⍳⍨(+/⊢=⊢∧⍳)¨⍳2*⍵}
アダム

定義する必要はないと思うf
ザカリー

5

GolfScript、29 28文字

{.{\.,{)1$\%},,-=}+2@?,?}:f;

編集:検索を<2 ^ nに制限すると、単一の文字を保存できます。このアイデアはPeter Taylorのおかげです。

前のバージョン:

{.{\)..,{)1$\%},,-@=!}+do}:f;

GolfScriptでの試みは、オンライン実行します

例:

13 f p  # => 4096
14 f p  # => 192
15 f p  # => 144

コードには、基本的に3つのブロックが含まれています。これらのブロックについては、次の行で詳しく説明します。

# Calculate numbers of divisors
#         .,{)1$\%},,-    
# Input stack: n
# After application: D(n)

.,          # push array [0 .. n-1] to stack
{           # filter array by function
  )         #   take array element and increase by one
  1$\%      #   test division of n ($1) by this value
},          # -> List of numbers x where n is NOT divisible by x+1
,           # count these numbers. Stack now is n xd(n)
-           # subtracting from n yields the result



# Test if number of divisors D(n) is equal to d
#         {\D=}+   , for D see above
# Input stack: n d
# After application: D(n)==d

{
  \         # swap stack -> d n
  D         # calculate D(n) -> d D(n)
  =         # compare
}+          # consumes d from stack and prepends it to code block         



# Search for the first number which D(n) is equal to d
#         .T2@?,?    , for T see above
# Input stack: d
# After application: f(d)

.           # duplicate -> d d
T           # push code block (!) for T(n,d) -> d T(n,d)
2@?         # swap and calculate 2^d -> T(n,d) 2^d
,           # make array -> T(n,d) [0 .. 2^d-1]
?           # search first element in array where T(n,d) is true -> f(d)

入力のために無限ループに入るよう1です。
ピーターテイラー

これまでの私の最善の解決策は、個別の回答ではなくコメントに値する範囲で、あなたから非常に大きく借りています。
ピーターテイラー

4

Python:64

Bakuriuのソリューションを修正し、grcの提案とplannapusのRソリューションからのトリックを組み込むと、次のようになります。

f=lambda n,k=1:n-sum(k%i<1for i in range(1,k+1))and f(n,k+1)or k

4

Python:66

f=lambda n,k=1:n==sum(k%i<1for i in range(1,k+1))and k or f(n,k+1)

上記はRuntimeError: maximum recursion depth exceededCPythonで小さな入力でa を発生させ、制限を巨大な数に設定しても、おそらくいくつかの問題が発生します。末尾再帰を最適化するpython実装では、正常に動作するはずです。

このような制限はないはずのより冗長なバージョンは、次の79バイトのソリューションです。

def f(n,k=1):
    while 1:
        if sum(k%i<1for i in range(1,k+1))==n:return k
        k+=1

11、13、17、19、およびその他の再帰制限に達しました。
スティーブンランバルスキー

@StevenRumbalskiプログラムが任意の整数で動作するはずだと言う人はいません。残念ながら、小さな入力でも数値はかなり速く成長します。
バクリウ

あなたは置き換える使用して一部の文字を保存することができif elseand or==1して<1f=lambda n,k=1:n==sum(k%i<1for i in range(1,k+1))and k or f(n,k+1)
GRC

66は少し悪すぎると思うので、使用すると2文字節約できますsum(k%-~i<1for i in range(k))
ボラティリティ

f=lambda n,k=1:n==sum(k%-~i<1for i in range(k))or-~f(n,k+1)7バイトを節約します。
デニス

4

Mathematica 38 36

(For[i=1,DivisorSum[++i,1&]!=#,];i)&

使用法:

(For[i=1,DivisorSum[++i,1&]!=#,];i)&@200

結果:

498960

編集

いくつかの説明:

DivisorSum [n、form]は、nを分割するすべてのiのform [i]の合計を表します。

form[i]私は、関数を使用しています1 &常にリターンがあること、1ので、効果的に簡潔な方法で約数の和を計算します。


code-golfタグがなかったので、長い回答をしました!おっと
DavidC

@DavidCarraher推測したところです。)
ベリサリウス博士13

DivisorSumが返されるか(除数の合計)はわかっていたと思いましたが、それが提起された質問に答えるためにどのように役立つかわかりません。それがどのように機能するか説明してください。ところで、n = 200のタイミングデータを含めるべきだと思います。チェックする必要のあるすべての数値を考えると、この関数は非常に高速です。
DavidC

@DavidCarraher編集を参照してください。Re:タイミング-マシンが遅
すぎる

Mathematicaには、ファクタリングを短縮するためのより洗練されたアプローチのための十分な組み込み機能がありませんか?その場合、私は失望しています。
ピーターテイラー

3

J、33文字

かなり高速で、すべての小さい数値を調べ、因数分解に基づいて除数の数を計算します。

   f=.>:@]^:([~:[:*/[:>:_&q:@])^:_&1

   f 19
262144

3

ハスケル54

早くて汚い(とても読みやすくて扱いにくい)ソリューション:

f k=head[x|x<-[k..],length[y|y<-[1..x],mod x y==0]==k]

この編集は答えを短くしませんでしたが、多分もっとハスケルのようなものです。また、コードの長さに末尾の改行を常に含めていますが、これは間違っていますか?
塩奈

あなたが間違って数えたと思った。編集の主な目的は、カウントを更新することでした。コード自体の変更はわずかでした。ここの他のエントリも、たとえばJ(33文字)のエントリのように、末尾の改行をカウントしないと思います。
ウィルネス

2

K、42

スタックを簡単に爆破する非効率的な再帰的ソリューション

{{$[x=+/a=_a:y%!1+y;y;.z.s[x;1+y]]}[x;0]} 

k){{$[x=+/a=_a:y%!1+y;y;.z.s[x;1+y]]}[x;0]}14
192
k){{$[x=+/a=_a:y%!1+y;y;.z.s[x;1+y]]}[x;0]}13
'stack


2

APL(25)

{⍵{⍺=+/0=⍵|⍨⍳⍵:⍵⋄⍺∇⍵+1}1}

不正行為!echo -n '{⍵{⍺= + / 0 =⍵|⍨⍳⍵:⍵⋄⍺∇⍵+ 1} 1}' | wc -cは47を与えてくれます!しかし、実際には、APLの簡単なチュートリアルへのリンクを教えてください。私はそれをグーグルで試し、いくつかの記事を読みましたが、最終的には「なぜ彼らはこれをやっているのですか:(?」と尋ねたいと思います。それはどんな本当の利点を持っている。
XzKto

これは、私が使用しているDyalog APL用です。同じサイトからWindowsバージョンを無料でダウンロードできます。dyalog.com/MasteringDyalogAPL/MasteringDyalogAPL.pdf
マリヌス

うわー、私はこれを本当に理解できるように見えます。リンクありがとうございます!唯一の欠点は、非常に奇妙なライセンスポリシーがあることですが、たぶん英語を改善する必要があるだけです)
-XzKto

2

R-47文字

f=function(N){n=1;while(N-sum(!n%%1:n))n=n+1;n}

!n%%1:nブール値のベクトルを返します。1〜nの整数がnの約数である場合はTRUE、そうでない場合はFALSEです。sum(!n%%1:n)ブール値をFALSEの場合N-sum(...)は0に、TRUEの場合は1に強制して合計します。したがって、除数の数がNの場合は0になります。while、停止します。

使用法:

f(6)
[1] 12
f(13)
[1] 4096

2

Javascript 70

function f(N){for(j=i=m=1;m-N||j-i;j>i?i+=m=j=1:m+=!(i%++j));return i}

本当に意味のある文字は46個だけです。

for(j=i=m=1;m-N||j-i;j>i?i+=m=j=1:m+=!(i%++j))

私はおそらくより短い構文で言語を学ぶべきです:)


N=>eval("for(j=i=m=1;m-N||j-i;j>i?i+=m=j=1:m+=!(i%++j));i")
TuxCrafting

2

Haskell:49文字

それは以前のHaskellソリューションの改善と見ることができましたが、それ自体で考えられていました(警告:非常に遅いです):

f n=until(\i->n==sum[1|j<-[1..i],rem i j<1])(+1)1

これは非常に興味深い関数です。たとえば、f(p)= 2 ^(p-1)であることに注意してください。ここで、pは素数です。


それが要因となり計算する効率的な、短いとは対照的に、方法n(反復で)素数にソート降順に、それぞれをデクリメント、素数の無限配列を有するジッパー、及びその後の積倍p^(factor-1)
ピーター・テイラー

2
@PeterTaylor必要ありません。n = 16 = 2 * 2 * 2 * 2の場合、解は2 ^ 3 * 3 ^ 1 * 5 ^ 1 = 120であり、2 ^ 1 * 3 ^ 1 * 5 ^ 1 * 7 ^ 1 = 210ではありません。
randomra

2

C:66 64文字

ほとんど短い解決策:

i;f(n){while(n-g(++i));return i;}g(j){return j?!(i%j)+g(j-1):0;}

そして、再帰しない私の以前のソリューション:

i;j;k;f(n){while(k-n&&++i)for(k=0,j=1;j<=i;k+=!(i%j++));return i;}

はるかに短いソリューションが存在する必要があります。


2

Haskell(120C)、非常に効率的な方法

1<>p=[]
x<>p|mod x p>0=x<>(p+1)|1<2=(div x p<>p)++[p]
f k=product[p^(c-1)|(p,c)<-zip[r|r<-[2..k],2>length(r<>2)](k<>2)]

テストコード:

main=do putStrLn$show$ f (100000::Integer)

この方法は非常に高速です。アイデアは、の素因数を見つけることですk=p1*p2*...*pm。ここで、p1 <= p2 <= ... <= pmです。それから答えはn = 2^(pm-1) * 3^(p(m-1)-1) * 5^(p(m-2)-1) ...

たとえば、k = 18を因数分解すると、18 = 2 * 3 * 3になります。最初の3つの素数は2、3、5です。したがって、答えn = 2 ^(3-1)* 3 ^(3-1)* 5 ^(2-1)= 4 * 9 * 5 = 180

以下でテストできますghci

*Main> f 18
180
*Main> f 10000000
1740652905587144828469399739530000
*Main> f 1000000000
1302303070391975081724526582139502123033432810000
*Main> f 100000000000
25958180173643524088357042948368704203923121762667635047013610000
*Main> f 10000000000000
6558313786906640112489895663139340360110815128467528032775795115280724604138270000
*Main> f 1000000000000000
7348810968806203597063900192838925279090695601493714327649576583670128003853133061160889908724790000
*Main> f 100000000000000000
71188706857499485011467278407770542735616855123676504522039680180114830719677927305683781590828722891087523475746870000
*Main> f 10000000000000000000
2798178979166951451842528148175504903754628434958803670791683781551387366333345375422961774196997331643554372758635346791935929536819490000
*Main> f 10000000000000000000000
6628041919424064609742258499702994184911680129293140595567200404379028498804621325505764043845346230598649786731543414049417584746693323667614171464476224652223383190000

これはゴルフのスコアとしては劣りますが、これまでに行ったパスに対して+1です!
-SteeveDroz

8 = 2 * 2 * 2の場合、このアルゴリズムは番号2 * 3 * 5 = 30を与えます。しかし、最善の解決策は2 ^ 3 * 3 = 24(8 = 2 * 4の場合)
AMK

指定された数の除数に小さいべき乗の高いべき乗が含まれる場合、解は正しくありません。したがって、10のべき乗のリストにある可能性が最も高いソリューションは間違っています。
AMK

@AMKはい、そうです。それを指摘してくれてありがとう。
レイ

2

Brachylog、2バイト

fl

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

出力変数を介して入力を受け取り、入力変数を介して出力します。

f     The list of factors of
      the input variable
 l    has length equal to
      the output variable.

入力変数を介して入力を取得し、出力変数を介して出力するこのまったく同じ述語は、代わりにこの課題を解決します


言語は質問よりも新しいため、このパズルには適していません。
SteeveDroz

:私は新しいここに私が言われた最初のものの一つであった場合は質問より新しい言語はもう非競合していない、これはメタによってバックアップされているということであったcodegolf.meta.stackexchange.com/questions/12877/...
関連のない文字列の

まあ、それでは気にしないで。どうやら、ルールは進化するように作られており、このサイトの主な目的は自分自身を改善し、楽しむことであることに留意する必要があります。回答が受け入れられました!
-SteeveDroz

1

C、69文字

最短ではなく、最初のCの回答:

f(n,s){return--s?f(n,s)+!(n%s):1;}
x;
g(d){return++x,f(x,x)-d&&g(d),x;}

f(n,s)nの範囲の約数を数えます1..s。のf(n,n)約数を数えnます。
g(d)ループするまで(再帰によって)ループしf(x,x)==d、xを返します。


1

Mathematica 38 36

(For[k=1,DivisorSigma[0, k]!= #,k++]; k)&

使用法

   (For[k = 1, DivisorSigma[0, k] != #, k++]; k) &[7]

(* 64 *)

最初のエントリcode-golfタグが質問に追加される前)

(を含む)のDivisors[n]約数を返し、そのような約数の数を返すという単純な問題。**nnLength[Divisors[n]]

smallestNumber[nDivisors_] :=
   Module[{k = 1},
   While[Length[Divisors[k]] != nDivisors, k++];k]

Table[{i, nDivisors[i]}, {i, 1, 20}] // Grid

Mathematicaグラフィックス


デビッド、短く、より速くよりLength@Divisors@nですDivisorSigma[0,n]
ミスターウィザード

ありがとう。私はその使用について知らなかったDivisorSigma
-DavidC


1

ゼリー、6 バイト(非競合)

2*RÆdi

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

使い方

2*RÆdi  Main link. Argument: n (integer)

2*      Compute 2**n.
  R     Range; yield [1, ..., 2**n]. Note that 2**(n-1) has n divisors, so this
        range contains the number we are searching for.
   Æd   Divisor count; compute the number of divisors of each integer in the range.
     i  Index; return the first (1-based) index of n.

どうして2*ですか?それ以降のすべての数値には、nよりも多くの約数がありますか?
エリックアウトゴルファー

2
番号; たとえば、すべての素数には正確に2つの除数があります。ただし、除数がnの最小の正の整数を検索しています。その範囲に属しているので、最小のものも同様です。2**(n-1)
デニス


0

Python2、95文字、非再帰的

他のpythonソリューションよりも少し冗長ですが、再帰的ではないため、cpythonの再帰制限に達しません。

from itertools import*
f=lambda n:next(i for i in count()if sum(1>i%(j+1)for j in range(i))==n)

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