计算实际数字


18

定义

正整数n是一个实际数字(OEIS序列A005153),前提是所有较小的正整数都可以表示为的不同除数之和n

例如,18是一个实际数字:其除数为1、2、3、6、9和18,小于18的其他正整数可以形成如下:

 4 = 1 + 3          5 = 2 + 3           7 = 1 + 6
 8 = 2 + 6          10 = 1 + 9         11 = 2 + 9
12 = 3 + 9 = 1 + 2 + 9 = 1 + 2 + 3 + 6
13 = 1 + 3 + 9      14 = 2 + 3 + 9      15 = 6 + 9
16 = 1 + 6 + 9      17 = 2 + 6 + 9

但这14不是一个实际数字:它的除数是1、2、7和14,并且没有这些因数的子集加到4、5、6、11、12或13。

挑战

编写一个程序,函数或动词,以正整数作为输入,x并返回或打印第x 实际数字,该数字从1开始索引,以与OEIS保持一致。您的代码必须足够高效,才能在合理的台式计算机上在不到两分钟的时间内处理多达250000个输入。(注意,我在Java中的参考实现在不到0.5秒的时间内管理250000,而我在Python中的参考实现在12秒内管理它)。

测试用例

Input        Expected output
1            1
8            18
1000         6500
250000       2764000
1000000      12214770
3000000      39258256

(恕我直言)如果赢得了最快的代码(每种语言?),这甚至可能会变得很有趣
显示名称

4
@SargeBorsch因此,您将在答案中看到250K条目的表格
belisarius博士2014年

@belisarius好点。但是我认为这种作弊很容易被禁止。否则问题可能需要任意数字的正确答案,但是使用标准库中没有大整数的语言来进行编码时会遇到困难...:/
显示名称

我正在考虑一种算法优化方法,但是根据当前规则,我懒得实现它:P
显示名称

4
@SargeBorsch,如果您不想打高尔夫球,请随时将其代码上传到gist.github.com之类的地方,并在此处的注释或聊天中添加链接。FWIW我更喜欢具有慷慨性能约束的代码,而不是最快的代码,这有两个原因:首先,代码的长度更客观地可测量;其次,它引入了一个权衡因素:可以省去哪些速度优化以缩短代码而不破坏性能?
彼得·泰勒

Answers:


5

J(99个字符)

f=:3 :0
'n c'=.0 1
while.c<y do.
'p e'=.__ q:n=.n+2
c=.c+*/(}.p)<:}:1+*/\(<:p^e+1)%<:p
end.
n+n=0
)

由于问题陈述要求输入“程序,函数或动词 ”,因此必须有人提交J陈述。J人会注意到我并不是真正的高尔夫(!)或没有对此进行优化。像其他条目一样,我使用OEIS链接中提到的Stewart定理来测试每个偶数是否可行。

我没有安装J的“合理的台式计算机”的访问权限。在我六岁的上网本上,f 250000计算时间为120.6秒,还不到两分钟,但是大概在任何更合理的计算机上,这都能及时完成。


6

Mathematica,126 121个字符

感谢belisarius。

在维基百科上使用公式。

f=(i=j=1;While[j<#,If[And@@Thread[#[[;;,1]]<2+Most@DivisorSum[FoldList[#Power@@#2&,1,#],#&]&@FactorInteger@++i],j++]];i)&

例子:

f[1]

1个

f[8]

18岁

f[250000]

2764000

f[250000]在我的计算机上计算花费了70年代。


3
我认为您可以绕过奇整数而以一个字符为代价获得更好的性能
belisarius博士2014年

1
为了减少OEIS提交中的代码,您的执行速度降低了10倍。只是想知道,“为什么您认为您的代码比OEIS示例运行得慢得多?”
DavidC 2014年

@belisarius您的建议将时间缩短了一半。
DavidC 2014年

2
相同的119个字符:(i=j=1;While[j<#,If[And@@Thread[#[[;;,1]]<2+Most@DivisorSum[FoldList[#Power@@#2&,1,#],#&]&@FactorInteger@++i],j++]];i)&
belisarius博士2014年

3

哈斯克尔-329

s 1=[]
s n=p:(s$div n p)where d=dropWhile((/=0).mod n)[2..ceiling$sqrt$fromIntegral n];p=if null d then n else head d
u=foldr(\v l@((n,c):q)->if v==n then(n,c+1):q else(v,1):l)[(0,1)]
i z=(z<2)||(head w==2)&&(and$zipWith(\(n,_)p->n-1<=p)(tail n)$scanl1(*)$map(\(n,c)->(n*n^c-1)`div`(n-1))n)where w=s z;n=u w
f=((filter i[0..])!!)

例子:

> f 1
1
> f 13
32
> f 1000
6500

这是一个小型测试套件(位于上面):

import Data.Time.Clock
import System.IO

test x = do
    start <- getCurrentTime
    putStr $ (show x) ++ " -> " ++ (show $ f x)
    finish <- getCurrentTime
    putStrLn $ " [" ++ (show $ diffUTCTime finish start) ++ "]"

main = do
    hSetBuffering stdout NoBuffering
    mapM_ test [1, 8, 1000, 250000, 1000000, 3000000]

使用ghc -O3以下命令编译后的测试结果:

1 -> 1 [0.000071s]
8 -> 18 [0.000047s]
1000 -> 6500 [0.010045s]
250000 -> 2764000 [29.084049s]
1000000 -> 12214770 [201.374324s]
3000000 -> 39258256 [986.885397s]

当我用ghci尝试时,它会抱怨parse error on input `='。我是否需要使用一些标志或其他标志?
彼得·泰勒

1
@PeterTaylor您不能像这样将函数定义粘贴到ghci中。您最简单的方法是将其保存asdf.hs并运行ghci asdf.hs,然后从那里可以访问f
mniip 2014年

@PeterTaylor ghc --make -O3 [filename]。您也可以将其加载到ghci中,:l [filename]但考虑到编译时间的限制可能是最好的。:)
乔纳森·范·马特雷

如上面的注释所示,@ JonathanVanMatre ghci加载其参数中指定的文件
mniip 2014年

喔好吧。同时,我已经将它与您的测试框架和一起运行ghc。您的计算机的速度比我的计算机快,但在98秒的时间里,它仍然在计算机的性能标准之内。
彼得·泰勒

2

JavaScript中,306 307 282B

function y(r){for(n=r-1,k=1;n;k++)if(p=[],e=[],c=0,P=s=1,!((x=k)%2|1==x)){while(x>1){for(f=x,j=2;j<=Math.sqrt(f);j++)if(f%j==0){f=j;break}f!=p[c-1]?(p.push(f),e.push(2),c++):e[c-1]++,x/=f}for(i=0;c>i;i++){if(p[i]>P+1){s=0;break}P*=(Math.pow(p[i],e[i])-1)/(p[i]-1)}s&&n--}return k-1}

约250k 我的笔记本电脑上的6s。

已注释的取消注释的代码:http : //jsfiddle.net/82xb9/3/现在具有更好的sigma测试和更好的if条件(谢谢您的评论)

预编辑版本:http//jsfiddle.net/82xb9/ http://jsfiddle.net/82xb9/1/


这个问题确实问一个函数或程序(JS没有动词),所以不是不计第一行,你应该换一个函数声明第二线并更换最后k--;return k-1。虽然稍微增加你的字节数,你可以保存的东西几下就好替换p[i]>=P+2p[i]>P+1(可能通过移除内部函数调用和使用break代替)。
彼得·泰勒

我认为“ testing sigma”部分的大小和速度都可以重写:jsfiddle.net/3DTSa。尽管此JS解决方案非常快。
user2846289 2014年
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.