関数は自然数を取り、それ自体を含む正確にその数の除数を持つ最小の自然数を返します。
例:
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]
...
この関数は除数のリストを返す必要はありません。それらは例のためだけにあります。
関数は自然数を取り、それ自体を含む正確にその数の除数を持つ最小の自然数を返します。
例:
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]
...
この関数は除数のリストを返す必要はありません。それらは例のためだけにあります。
回答:
f←{({+/⍵=⍵∧⍳⍵}¨⍳2*⍵)⍳⍵}
f
数値の計算に使用できる関数を定義します。
> f 13
4096
> f 14
192
ソリューションは、xがnを除算する場合、LCM(n、x)== nという事実を利用します。したがって、ブロック{+/⍵=⍵∧⍳⍵}
は除数の数を単純に計算します。この関数は1から2 ^ d までのすべての数値に適用されます¨⍳2*⍵
。次に、結果のリストからd自体(⍳⍵
)が検索されます。これは、目的の関数f(d)です。
{⍵⍳⍨(+/⊢=⊢∧⍳)¨⍳2*⍵}
f
。
{.{\.,{)1$\%},,-=}+2@?,?}:f;
編集:検索を<2 ^ nに制限すると、単一の文字を保存できます。このアイデアはPeter Taylorのおかげです。
前のバージョン:
{.{\)..,{)1$\%},,-@=!}+do}:f;
例:
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
です。
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 exceeded
CPythonで小さな入力で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
if else
てand or
と==1
して<1
:f=lambda n,k=1:n==sum(k%i<1for i in range(1,k+1))and k or f(n,k+1)
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バイトを節約します。
(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
ので、効果的に簡潔な方法で約数の和を計算します。
DivisorSum
が返されるか(除数の合計)はわかっていたと思いましたが、それが提起された質問に答えるためにどのように役立つかわかりません。それがどのように機能するか説明してください。ところで、n = 200のタイミングデータを含めるべきだと思います。チェックする必要のあるすべての数値を考えると、この関数は非常に高速です。
{⍵{⍺=+/0=⍵|⍨⍳⍵:⍵⋄⍺∇⍵+1}1}
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")
それは以前の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)
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
fl
出力変数を介して入力を受け取り、入力変数を介して出力します。
f The list of factors of
the input variable
l has length equal to
the output variable.
入力変数を介して入力を取得し、出力変数を介して出力するこのまったく同じ述語は、代わりにこの課題を解決します。
(For[k=1,DivisorSigma[0, k]!= #,k++]; k)&
使用法
(For[k = 1, DivisorSigma[0, k] != #, k++]; k) &[7]
(* 64 *)
最初のエントリ(code-golf
タグが質問に追加される前)
(を含む)のDivisors[n]
約数を返し、そのような約数の数を返すという単純な問題。**n
n
Length[Divisors[n]]
smallestNumber[nDivisors_] :=
Module[{k = 1},
While[Length[Divisors[k]] != nDivisors, k++];k]
例
Table[{i, nDivisors[i]}, {i, 1, 20}] // Grid
Length@Divisors@n
ですDivisorSigma[0,n]
。
DivisorSigma
。
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**(n-1)
{my \a=$=0;a++while $_-[+] a X%%1..a;a}
使用例:
say (0..10).map: {my \a=$=0;a++while $_-[+] a X%%1..a;a}
(0 1 2 4 6 16 12 64 24 36 48)