给出具有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
这是代码高尔夫还是代码挑战?
marinus 2013年

糟糕,忘记了这个标签,代码高尔夫!
SteeveDroz

Answers:


6

APL,25 24 23个字符

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

定义一个函数f,然后可以使用该函数来计算数字:

> f 13
4096

> f 14
192

该解决方案利用LCM(n,x)== n的事实,如果x除以n。因此,该块{+/⍵=⍵∧⍳⍵}仅计算除数的数量。此函数适用于从12 ^ 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

该代码本质上包含三个块,下面各行将对其进行详细说明。

# 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

蟒蛇: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

我要达到11、13、17、19等的递归限制。
Steven Rumbalski

@StevenRumbalski没有人提到该程序应使用任意整数。不幸的是,即使输入很少,数字也会快速增长。
Bakuriu 2013年

您可以通过使用替代节省一些字符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))
Volatility 2013年

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,因此可以用简洁的方式有效地计算除数之和。


没有代码标记,所以我给出了一个很长的答案!哎呀
DavidC

我刚刚猜到
了@DavidCarraher

我以为我知道DivisorSum返回的结果(除数的总和),但是我不认为这对回答所提出的问题有什么帮助。您能解释一下它是如何工作的。顺便说一句,我认为您应该包括n = 200的时序数据;考虑到必须检查的所有数字,该功能非常快。
DavidC 2013年

@DavidCarraher参见编辑。回复:计时-我的机器太慢了:(
belisarius博士13年

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]

该编辑并没有使答案更短,但可能更像haskell。另外,我总是在代码长度中包含尾随换行符,这是错误的吗?
shiona 2013年

我以为你算错了;编辑的主要目的是更新计数。代码本身的更改很小。我认为这里的其他条目也不计末尾的换行符,例如J(33个字符)的条目。
Will Ness 2013年

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

杀伤人员地雷33

F n            
i←0              
l:i←i+1          
→(n≠+/0=(⍳i)|i)/l
i 

例:

F 6
12           

2

APL(25)

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

骗子!echo -n'{⍵{⍺= + / 0 =⍵|⍨⍳⍵:⍵⋄⍺∇⍵+ 1} 1}'| wc -c给了我47!但是,真的,您能给我链接一些简单的APL教程吗?我试图用Google搜索它,并读了几篇文章,但最后我还是想问“他们为什么这样做:( ??”。我从未使用过任何非ASCII语法语言,并且想知道是否它具有任何真正的优势
XzKto

这是我使用的Dyalog APL,您可以在同一站点上免费下载Windows版本。dyalog.com/MasteringDyalogAPL/MasteringDyalogAPL.pdf
marinus

哇,看起来我真的可以理解这一点。谢谢你的链接!唯一的缺点是他们有一些非常奇怪的许可政策,但也许我只需要提高我的英语水平)
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,则将布尔值强制为0;如果为TRUE,则将布尔值强制为1并将它们求和。因此,N-sum(...)如果除数为N ,则布尔值为0。然后,将0解释为FALSE 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's October

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)
Peter Taylor

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

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。前三个素数是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 2013年

如果指定数量的除数包含小质数的高幂,则解决方案不正确。因此,最有可能列出的幂为10的解决方案是错误的。
AMK 2013年

@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]返回nn)的除数并Length[Divisors[n]]返回这样的除数的数量。**

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

例子

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

Mathematica graphics


大卫,比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
没有; 例如,所有素数都恰好有两个除数。但是,我们正在搜索具有n个除数的最小正整数。由于属于该范围,因此最小的范围也是如此。2**(n-1)
丹尼斯,

0

C ++,87个字符

int a(int d){int k=0,r,i;for(;r!=d;k++)for(i=2,r=1;i<=k;i++)if(!(k%i))r++;return k-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)

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.