一百万以下的素数清单


56

这是我的第一个高尔夫问题代码,也是一个非常简单的问题,因此,如果我可能违反了任何社区准则,我事先表示歉意。

任务是按升序打印所有小于一百万的质数。输出格式应为每行输出一个数字。

与大多数代码高尔夫球提交一样,其目的是最小化代码大小。针对运行时进行优化也是一个奖励,但它是次要目标。


12
它不是精确的重复项,而是本质上只是素数测试,它是许多现有问题的一部分(例如,codegolf.stackexchange.com / questions / 113codegolf.stackexchange.com / questions / 5087codegolf.stackexchange。 com / questions / 1977)。FWIW的一项指南(即使是应该更了解的人)也没有得到足够的遵循,它是在meta沙箱meta.codegolf.stackexchange.com/questions/423中预先提出一个问题,以提出批评和讨论。在人们开始回答之前有所改善。
彼得·泰勒

嗯,是的,我担心这个问题与已经存在的过多与质数有关的问题过于相似。
Delan Azabani 2012年

2
@ GlennRanders-Pehrson因为10^6更短;)
ɐɔıʇǝɥʇuʎs2014年

1
几年前,我提交了打印素数只有68个C字符的IOCCC入门-不幸的是它停止远远低于一百万,但它可能会感兴趣的一些:computronium.org/ioccc.html
Computronium

1
@ɐɔıʇǝɥʇuʎs怎么样1e6:-D
Titus

Answers:


33

Mathematica17 24

只是为了比较:

Prime@Range@78498

正如评论中指出的那样,我未能为每行提供一个素数。更正:

Column@Prime@Range@78498

4
Prime~Array~78498也是17 :)
chyanog 2014年

如果要释放的话,在mthmca中将是9个字节。
迈克尔·斯特恩

这违反了每行输出一个素数的条件。前缀Print/@和终止;以防止输出较长的Nulls修订列表,但要花8个额外字符。
celtschk

@celtschk我不知道五年前是错过还是忽略了我。
威兹德先生

1
好吧,我绝对
想不到

27

Python 3,46个字节

k=P=1
while k<1e6:P%k and print(k);P*=k*k;k+=1

在循环到达测试时k,它已经迭代计算了平方乘方P=(k-1)!^2。如果k是质数,则它不会出现在产品中1 * 2 * ... * (k-1),因此不是的因子P。但是,如果是复合材料,则所有主要因素都较小,因此在产品中也是如此。实际上仅需要平方才能阻止k=4错误地称为素数。

更强烈地,从威尔逊定理得出,当k素数为时,P%k等于1。尽管在这里我们只需要它不为零,但一般来说,它P%k是判断是否k为质数的指标变量很有用。


23

C,61个字符

几乎完全相同(问题也几乎完全相同)。

n=2;main(m){n<1e6&&main(m<2?printf("%d\n",n),n:n%m?m-1:n++);}

SEG-FAULT打印后得到881
manav mn 2014年

7
@Manav,也许您编译时没有优化。它依赖于一个好的优化器,它将消除递归。
ugoren 2014年

4
是的,-O3可以gcc解决问题!!
manav mn 2014年

这种方法太疯狂了。我喜欢它。
托德·雷曼

2
我可以给您提供57个字节n=2;main(m){n<1e6&&main(m<2?printf("%d\n",n),n:m-++n%m);}
阿尔伯特·伦肖2016年

22

MATLAB (16)(12)

不幸的是,这是一行输出:

primes(1000000)

但这可以通过一个简单的矩阵转置来解决:

primes(1000000)'

并且我可以使用指数表示法(如注释中建议的那样)切出一些字符:

primes(1e6)'

5
在这里也使用1e6代替而不是1000000帮助。
Orion

@orion这将使其成为11个字符
Axoren 2014年

@Axoren即不包括'在端部
斯坦斯特鲁姆

20

重击(37个字符)

seq 2 1e6|factor|sed 's/.*: //g;/ /d'

(60个字符)

seq 2 1000000|factor|sed -e 's/[0-9]*: //g' -e '/^.* .*$/ d'

在我的计算机上(2.0 GHz CPU,2 GB内存)需要14秒。


可以将其改进为: seq 2 1000000|factor|sed 's/[0-9]*: //g;/^.* .*$/ d'
Delan Azabani 2012年

你是对的。我将sed命令写得很干净,而不是打高尔夫球:P
2012年

3
seq 1e6|factor|awk '$0=$2*!$3'有点短。
丹尼斯

1
seq,factor和sed是外部程序,这也可能是c pc是与cat的符号链接,而p是素数最大为一百万的文本文件...您可以使用shell内置函数来做到这一点吗?
Technosaurus

7
@technosaurus seq并且factor位于中coreutils,因此是合法的。sed也很普遍。 coreutils可以像内置的一样对待。没有coreutils的Bash就像没有STL的C ++。

16

J,21个字符

1[\p:i.(_1 p:1000000)

可以缩短为

1[\p:i.78498

如果您知道1000000以下有多少个素数。


2
使用enfile项(,.而不是1 [\\)保存字符。删除不必要的括号,然后使用指数符号:1e6
奥马尔

,.i.&.(p:^:_1)1e6想到了:不短(在应用@Omar的建议之后),但是我发现under的使用很有趣。
kaoD

10

PowerShell,47 44字节

非常慢,但我能想出的最短。

$p=2..1e6;$p|?{$n=$_;!($p-lt$_|?{!($n%$_)})}

PowerShell,123字节

这要快得多;远非最佳,但在效率和简洁之间做出了很好的折衷。

 $p=2..1e6;$n=0
 while(1){$p=@($p[0..$n]|?{$_})+($p[($n+1)..($p.count-1)]|?{$_%$p[$n]});$n++;if($n-ge($p.count-1)){break}}
 $p


9

Bash,30个字节

由于saeedn不会按照我的建议行事-比他的方法短而且快-我想我会发表自己的答案:

seq 1e6|factor|awk '$0=$2*!$3'

这个怎么运作

seq 1e6

列出所有不超过1,000,000的正整数。

factor

将它们一一分解。对于前十个,输出如下:

1:
2: 2
3: 3
4: 2 2
5: 5
6: 2 3
7: 7
8: 2 2 2
9: 3 3
10: 2 5

最后,

awk '$0=$2*!$3'

将整行($0)更改为第二个字段(第一个素数)和第三个字段的逻辑取反的乘积(1如果等于或小于一个素数,0则否则)。

这会将与素数相对应的行替换为数字本身,并将所有其他行替换为零。由于awk仅打印真实值,因此只会打印质数。


4
awk '$0=$2*!$3'太酷了!
yeti 2014年

8

红宝石50 41

require'mathn'
p (2..1e6).select &:prime?

2
不需要.to_a,因为Enumerable已经包含了select。您也可以使用Symbol#to_proc的简写形式将其进一步缩短:p (2..1e6).select &:prime?(1不是质数)
Ventero,2012年

@Ventero非常感谢!我不知道Symbol#to_proc。我必须更加注意Ruby提供的快捷方式。
克里斯蒂安·卢帕斯库

2
短版require'prime';p Prime.take 78498
Hauleth 2013年

@ŁukaszNiemier太好了!我认为这是如此不同,您可以将其作为单独的答案发布。
Cristian Lupascu

很好地使用了一些不错的“乡村男孩数学”
DoctorHeckle

8

Bash,37岁

如果可以的话,还会打高尔夫吗?

多数情况下,这是试图解析factor尴尬的输出格式。

seq 1e6|factor|grep -oP "(?<=: )\d+$"

在我的计算机上完成需要5.7秒左右的时间。

(碰巧我的帖子是第一页出现在答案的第二页上,所以没人会看到它……)

旧解决方案

这会更长,更慢(耗时10秒)。

seq 1e6|factor|egrep ':.\S+$'|grep -oE '\S+$'

2
哇-我从没见过factor,但是coreutils就在那里!
Digital Trauma

1
剃掉一个字符:seq 1e6|factor|grep -oP "(?<=: )\d+$"用Perl的grep的回顾后
数字创伤

@DigitalTrauma的工作原理

1
-P启用perl样式的正则表达式。 (?<=: )是字符串“:” 的正向后缀。基本上说“:”必须在匹配项之前\d+$,但实际上不是匹配项的一部分,因此该-o选项只给我们一个冒号后面的匹配数,即仅给出只有一个因数(即质数)的数字。
Digital Trauma

@DigitalTrauma添加了

8

Python 3.x:66个字符

for k in range(2,10**6):
 if all(k%f for f in range(2,k)):print(k)

更有效的解决方案:87个字符

基于Eratosthenes筛。

p=[];z=range(2,10**6)
while z:f=z[0];p+=[f];z=[k for k in z if k%f]
for k in p:print(k)

1
第一个错误打印01。您可以改用来解决此问题range(2,10**6)。另外,我认为该if语句必须与列分开,for否则会出错。
xnor

@xnor:已修复。
2014年

8

Haskell,51岁

mapM print [n|n<-[2..10^6],all((>0).rem n)[2..n-1]]

您可以更改mapM_mapM,不打印返回值,这就是Code Golf。;)
Dogbert

为什么在打印后和(> 0)中有多余的空格?
骄傲的haskeller 2014年

不错的收获!谢谢
pt2121 2014年

您可以用10 ^ 6替换999999。并且请更新您的字节数-63可能不正确。
user2845840

@ user2845840好的,谢谢。好主意!
pt2121

8

APL,15

p~,p∘.×p←1↓⍳1e6

我的解释器遇到了内存问题,但理论上可行。


怎么样?可以请客吗?
2015年

您需要在前面加一个以使每行一个数字,并且不需要,
2015年

@RasmusDamgaardNielsen 是第一个整数。1↓删除第一个。p←分配给p。p∘.×p制作一个乘法表。p~从p删除右边的任何内容。(,不需要,它会将表格整理成列表。)
Adám2015年

8

Perl,49个字节

正则表达式功夫:)

for(1..1E6){(1x$_)=~/^(11+?)\1+$/ or print"$_\n"}

非高尔夫版本:

for(1 .. 1_000_000) { 
    (1x$_) =~ /^(11+?)\1+$/ or print "$_\n";
}

在我输入此信息时,它甚至还没有取得10%的进步!

正则表达式的来源:http : //montreal.pm.org/tech/neil_kandalgaonkar.shtml


2
启发我写了一个perl6版本。也1000000可以写成10**6
pabo

1
同样,可以将1000000写入1E6
暴民

更新了我的答案。感谢@mob
Gowtham

一直是我最喜欢的正则表达式,但是您需要记住,一旦获得更高的数字,它就会失败,因为它会将大量数字转换为一元。此正则表达式可能不会在成千上万的寻找素数及以后,因语言之一的配置工作(和你的机器。)
Codefun64

7

朱莉娅11岁

primes(10^6)

似乎内置组件正在获得好评,再加上我需要更多的单词才能获得更长的答案。


7

J(15或9)

我不能相信这一掌数学(即使它只是一个由2个字符)

a#~1 p:a=:i.1e6

要么:

p:i.78498

1
... The output format should be one number per line of output.这就是为什么我的答案始于1[\
Gareth 2014年

6

gs2,5个字节

在CP437中编码:

∟)◄lT

1C 29推百万,11 6C是下面的素数,54是显示线。


5

GolfScript,22/20(20/19)字节

n(6?,:|2>{(.p|%-.}do:n

为了提高速度,可以将代码缩短两个字节:

n(6?,:|2>.{|%2>-}/n*

如果忽略了在已编辑问题中指定的输出格式(许多现有答案都这样做),则可以在快速版本中保存两个字节,而在慢速版本中保存一个字节:

n(6?,:|2>{(.p|%-.}do
n(6?,:|2>.{|%2>-}/`

对于快速版本,这将在素数之后打印一个附加的LF,并将较慢的素数作为数组打印。

这个怎么运作

这两个版本都是Eratosthenes筛子的实现。

快速版本执行以下操作:

  1. 设置A = [ 2 3 4 … 999,999 ]| = [ 0 1 2 … 999,999 ]

  2. 设置N = A[0]并打印N

  3. 从收集每第N个元件|C。这些是的倍数N

  4. 设置A = A - C

  5. 如果A为非空,请返回2。

n(6?   # Push "\n".pop() ** 6 = 1,000,000.
,:|    # Push | = [ 0 1 2 … 999,999 ].
,2>    # Push A = [ 2 3 4 … 999,999 ].
{      #
  (    # Unshift the first element (“N”) of “A”.
  .p   # Print “N”.
  |%   # Collect every N-th element from “A” into a new array, starting with the first.
  -    # Take the set difference of “A” and the array from above.
  .    # Duplicate the set difference.
}do    # If the set difference is non-empty, repeat.
:n     # Store the empty string in “n”, so no final LF will get printed.

慢速版本以类似的方式工作,但不是连续删除最小的“ A”的倍数(始终为质数),而是删除小于1,000,000的所有正整数的倍数。

竞争力

在没有任何内置的数学函数可分解或检查素数的情况下,所有的GolfScript解决方案要么很大要么效率很低。

尽管距离效率还差得很远,但我认为我已经达到了不错的速度尺寸比。在提交该方法时,这种方法似乎是不使用任何上述内置方法的方法中最短的方法。我说似乎是因为我不知道某些答案的工作方式...

我已经对所有四个提交的GolfScript解决方案进行了基准测试:w0lf(试验部门),我的其他答案(Wilson定理)和这个答案中的两个。结果是:

Bound     | Trial division     | Sieve (slow)       | Wilson's theorem | Sieve (fast)
----------+--------------------+--------------------+------------------+----------------
1,000     | 2.47 s             | 0.06 s             | 0.03 s           | 0.03 s
10,000    | 246.06 s (4.1 m)   | 1.49 s             | 0.38 s           | 0.14 s
20,000    | 1006.83 s (16.8 m) | 5.22 s             | 1.41 s           | 0.38 s
100,000   | ~ 7 h (estimated)  | 104.65 (1.7 m)     | 35.20 s          | 5.82 s
1,000,000 | ~ 29 d (estimated) | 111136.97s (3.1 h) | 3695.92 s (1 h)  | 418.24 s (7 m)

“慢速”筛网只是Eratosthenes筛网吗?
dorukayhan

两者都是。慢版本只是一个可怕的实现。
丹尼斯

5

NARS2000 APL,7个字符

⍸0π⍳1e6

3
欢迎来到编程难题和代码高尔夫球!
丹尼斯

4

高尔夫脚本26 25 24

编辑(感谢Peter Taylor,又节省了一个字符):

10 6?,{:x,{)x\%!},,2=},`

旧代码:

10 6?,{.,{)\.@%!},,2=*},`

该代码仅具有理论价值,因为它非常慢且效率低下。我认为可能要花几个小时才能运行。

如果要测试,请尝试仅使用最多100的素数:

10 2?,{:x,{)x\%!},,2=},`

您可以将替换\;为来保存字符*。(通过查找第一个除数而不是全部除数,您也可以更快地获得当前字符数:10 6?,2>{.),2>{1$\%!}?=},`
彼得·泰勒

@PeterTaylor谢谢,使用乘法有一个非常巧妙的技巧。
克里斯蒂安·卢帕斯库

还有一个字符具有可变节省:更换.,:x,\.@x\ (空格是因为在评论与MD逃避问题),并删除*
彼得·泰勒

@PeterTaylor好人,谢谢!我已经编辑了代码。
Cristian Lupascu 2014年

4

果酱-11

1e6,{mp},N*

1e6,-0 ... 999999的数组
{mp},-选择素数
N*-与换行符连接


1
CJam是否比这个问题更新?
彼得·泰勒

@PeterTaylor哦,是的
-aditsu

4

GolfScript,25(24)字节

!10 6?,2>{.(@*.)@%!},n*\;

如果忽略了在已编辑问题中指定的输出格式,则可以保存一个字节:

!10 6?,2>{.(@*.)@%!},`\;

这将素数作为数组打印(就像许多其他解决方案一样),而不是每行打印一个。

这个怎么运作

一般的想法是使用威尔逊定理,该定理指出当且仅当n > 1为素数

                                                      (n-1)! = -1(mod n)

!     # Push the logical NOT of the empty string (1). This is an accumulator.
10 6? # Push 10**6 = 1,000,000.
,2>   # Push [ 2 3 4 … 999,999 ].
{     # For each “N” in this array:
  .(  # Push “N - 1”.
  @   # Rotate the accumulator on top of the stack.
  *   # Multiply it with “N - 1”. The accumulator now hold “(N - 1)!”.
  .)  # Push “(N - 1)! + 1”
  @   # Rotate “N” on top of the stack.
  %!  # Push the logical NOT of “((N - 1)! + 1) % N”.
},    # Collect all “N” for which “((N - 1)! + 1) % N == 0” in an array.
n*    # Join that array by LF.
\;    # Discard the accumulator.

基准测试

比审判部门快,但比Eratosthenes筛子慢。看到我的其他答案



3

C,91 88 85 82 81 80 76 72个字符

main(i,j,b){for(;i++<1e6;b++&&printf("%d\n",i))for(j=2;j<i;)b=i%j++&&b;}

该算法效率极低,但是由于我们正在执行代码高尔夫球,所以这无关紧要。


1
您可以轻松地缩短它:main(i,j,b){for(;i++<1e6;b++&&printf("%d\n",i))for(j=2;j<i;)b=i%j++&&b;}或类似这样的想法(因为我实际上没有编译它)
Ali1S232'5

如何i确定为0?我认为,如果您提供任何论点,它将失败。另外,我认为j会出现某种类型的错误。b虽然不确定。
暴民埃里克

3

Mathematica 25

假设您不知道小于10 ^ 6的素数:

Prime@Range@PrimePi[10^6]

3

J,16个字符

1]\(#~1&p:)i.1e6

如果没有输出格式要求,则可以减少到13个字符:

(#~1&p:)i.1e6

1]\ 只需将素数的第1列数组转换为素数第2的数组,然后将每个素数放在自己的行上-因此解释器的默认输出格式将单行列表变成每行一个素数。

(#~ f) y基本上是filter,其中f为中的每个元素返回一个布尔值yi.1e6是整数[0,1000000)的范围,并且1&p:是一个返回1的质数的布尔函数。


3

R,45 43个字符

for(i in 2:1e6)if(sum(!i%%2:i)<2)cat(i," ")

对于从2到1e6的每个数字x,如果x mod 2到x的x等于0的数量小于2,则只需输出。


此代码产生的第一个数字为1,但1不是质数。
Sven Hohenstein

@SvenHohenstein谢谢,纠正了。
plannapus

3

重击(433643)

我的尝试(不是那么聪明)是使用factor来分解产品。

factor ${PRODUCT}

不幸的是,大量产品当然是巨大的。运行还花费了超过12个小时。我决定发布它,因为我认为它是独一无二的。

这是完整的代码。

如果素数小于六,那将是合理的。

  factor 30

哦,我尝试过。


+1这个答案确实是邪恶的。并不是很精确的计算结果(它节省了很多字符),而且计算起来更加糟糕:)这很可能也是一个使优化后的factor性能比基本的试验划分算法差得多的示例。
Orion

3

C#,70

Enumerable.Range(1,1e6).Where(n=>Enumerable.Range(2,n).All(x=>x%n!=0))

你不会在这里看到很多东西了...


这是错误的几个原因。(1)您不能从a隐式转换double 1e6为an int,但是int是必需的Range。(2)内部Range必须使用最多的n-2术语,否则您将测试n % n清楚0。(3)x%n在需要时写n%x。解决这些问题后,类似的方法将起作用:Enumerable.Range(2,999999).Where(n=>Enumerable.Range(2,n-2).All(x=>n%x!=0))但是,这仍然不会输出数字。要求是每行一个。
杰普·斯蒂格·尼尔森
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.