自然产生的素数生成器


42

有很多主要的生成函数。它们几乎都是基于Eratosthenes筛子,Möbius函数或Wilson定理构造而成的,通常在实践中不可行。但是也有一些发电机,它们的结构非常简单,是偶然发现的。

2003年,Stephen Wolfram在NKS暑期学校的实时计算机实验中探索了一类嵌套递归方程。马修·弗兰克(Matthew Frank)周围的一群人进行了进一步的实验,发现了简单复发的有趣特征

a(n) = a(n-1) + gcd(n,a(n-1))

起始值为a(1) = 7。差异a(n) - a(n-1) = gcd(n,a(n-1))似乎总是1或素数。前几个区别是(OEIS A132199):

1, 1, 1, 5, 3, 1, 1, 1, 1, 11, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 3, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 47, 3, 1, 5, 3, ...

如果仅省略1,则会得到以下序列(OEIS A137613):

5, 3, 11, 3, 23, 3, 47, 3, 5, 3, 101, 3, 7, 11, 3, 13, 233, 3, 467, 3, 5, 3, 
941, 3, 7, 1889, 3, 3779, 3, 7559, 3, 13, 15131, 3, 53, 3, 7, 30323, 3, ...

几年后,埃里克·罗兰(Eric S. Rowland)证明了此列表中每个元素的优越性。如您所见,素数是混合的,其中一些素会出现多次。还已经证明,该序列包括无限多个不同的质数。此外,推测所有奇数素数都出现了。

因为该原发电机不是构造的,而是偶然发现的,所以该原发电机被称为“自然发生”。但是请注意,实际上,该生成器也很难进行计算。事实证明,素数p仅在(p–3)/2连续的1s 之后出现。但是,实现此主要生成器将是您的任务。

挑战:

编写一个函数或程序来打印n序列的第一个元素A137613(不带1的序列)。您可以n >= 0通过STDIN,命令行参数,提示或函数参数来读取输入数字。将n任何可读格式的第一个元素输出到STDOUT,或返回具有这些值的数组或列表。

这是代码高尔夫球。因此,以最短的代码为准。

排行榜:

这是一个堆栈片段,用于按语言生成常规排行榜和获胜者概述。为确保您的答案显示出来,请使用以下Markdown模板以标题开头。

# Language Name, N bytes

其中N是您提交的文件的大小。如果您提高了分数,则可以通过打败旧分数来保持标题。例如:

# Ruby, <s>104</s> <s>101</s> 96 bytes


1
虽然没有构造素数生成器,但是您正在使用递归有效地实现试验划分。
orlp

如果a(1)= 7,为什么序列不以7开头?
feersum

3
@feersum,因为我们关注的顺序是a(n)-a(n-1)
Maltysen

可以n为零吗?
Sp3000

1
@jrenk不确定。也许把它算作2个字节(因为您要删除2个chars //)并在您的提交中对其进行解释。如果有人不同意您的意见,您可以随时编辑自己的信息。
雅库布

Answers:



7

Python 3.5.0b1 +,95 93字节

链接到Python 3.5.0b1 +版本

import math
def f(k,n=2,a=7,L=[]):x=math.gcd(n,a);return k and f(k-1%x,n+1,a+x,L+1%x*[x])or L

直接执行重复周期,具有:

  • 我们的好朋友1%x,和
  • math.gcd相对于fractions.gcd

怎么1%x办?侧面问题:在哪里可以找到包含beta的Python修订历史记录的文档?编辑:没关系,在修订历史记录的底部找到了它。
mbomb007

@ mbomb007从x >= 11%x如果返回0 ,则返回0 x == 1,否则返回1(用于决定是否添加x到列表中)
Sp3000

5

朱莉娅110字节

n->(a(n)=(n1&&(n==1?7:a(n-1)+gcd(n,a(n-1))));i=2;j=0;while j<n x=a(i)-a(i-1);x>1&&(j+=1;println(x));i+=1end)

取消高尔夫:

function a(n::Int)
    n  1 && (n == 1 ? 7 : a(n-1) + gcd(n, a(n-1)))
end

function f(n::Int)
    i = 2;
    j = 0;
    while j < n
        x = a(i) - a(i-1)
        if x > 1
            j += 1
            println(x)
        end
        i += 1
    end
end

哇,完美的8k,不错:D
Beta Decay 2015年

1
使用n<2代替n==1。另外,如果你向前看,而不是向后的,你可以用i=1x=a(i)-a(i+=1),然后println(-x)-x>1以正确的消极情绪,从而避免了单独增加的需要i。并且是三个字节,>=而是两个...但是,然后,您可以使用n<1||()而不是n>=1&&()...,但是,它甚至根本没有必要(除去条件,n永远不会小于1)。在定义a(n)时,您也不需要最外面的括号。通过这些更改,您至少应减少到97个字节。
Glen O

5

PHP,101 96 99 98 77 72字节

<?for(;2>$t=gmp_strval(gmp_gcd(~++$i,7+$e+=$t))or$argv[1]-=print"$t ";);


用法:
使用以下参数调用脚本:php -d error_reporting=0 script.php 30
如果要测试它,则需要;extension=php_gmp.dll在php.ini中 取消注释
-> extension=php_gmp.dll
是否应将扩展名添加到字节数中?有什么想法吗?


日志:
感谢Ismael Miguel,节省了3个字节。
感谢primo,节省了26个字节。


1
您可以将开始标签缩短为,<?并删除的定义$j
Ismael Miguel 2015年

1
是的,很重要。但是您可以删除该换行符。这将节省1-2个字节,具体取决于您计算代码大小的方式。
Ismael Miguel 2015年

1
小的改进:使用<$j<=$argv[1](打印太多了)(-1)。保留$e未初始化状态,$e+7改为使用(-3)。使用for(;;)代替while(),并利用前置表达式和后置表达式(-2)。替换echo$t.' ';$j++$j+=print"$t ",放下括号(-3)。替换if($t>1)2>$t||(-2)。将分配$t与有条件的开关组合||or,放下括号(-5)。移动$argv[1]$j增量,将整个表达式移动到for条件(-2)。更改>=$j+=print-=print(-3)。逐步说明:codepad.org/s6LNSPSM
primo,

1
@primo感谢您的出色解释!不知道我能做所有这些。
jrenk

1
其他一些:$e+7$e+=$t(-2)组合。保留$i未初始化状态,~++$i改为使用(-3)。codepad.org/fDIImajp
普里莫

4

Haskell,51个字节

d=zipWith gcd[2..]$scanl(+)7d
f=($filter(>1)d).take

请注意,f此函数将返回前n个元素。

我们没有计算a(n)差异然后计算出差异,而是计算差异d(n)并将它们相加在一起得出a(n)。(那些不熟悉Haskell的人可能会抗议我们a(n)首先需要获得它d(n),但是懒惰的评估当然可以解决这个问题!)

取消高尔夫:

a = scanl (+) 7 d        -- yielding a(n) = 7 + d(1) + d(2) + ... + d(n-1)
d = zipWith gcd [2..] a  -- yielding d(n) = gcd(n+1, a(n))

f n = take n $ filter (> 1) d -- get rid of 1s and take the first n

4

Pyth,30个字节

打得很差,可以大大减少。在前面定义递归函数,过滤.first-n,然后映射差异。

L?tb+KytbibK7m-yhdyd.ft-yhZyZQ

在这里在线尝试


这给出了错误的输出n = 0
Sp3000 2015年

2
@ Sp3000是Pyth中的错误。我会提出拉取请求。
Maltysen,2015年

发现并修复错误-一旦github停止进行DDoS处理,便会实施补丁。
isaacg 2015年

1
它是:meta.codegolf.stackexchange.com/questions/5318/…。我个人认为编程语言中的错误修复是一个答案
Thomas Weller

2
@ThomasWeller这种实现了全部语言……
isaacg

4

朱莉娅69 67字节

n->(i=1;a=7;while n>0 x=gcd(i+=1,a);a+=x;x>1&&(n-=1;println(x))end)

这是对该问题的简单迭代解决方案。x是区别(即gcd),然后我a通过添加进行更新x


我认为它可以打印A231900
alephalpha

@alephalpha-我想我看到了错误。轻松修复。甚至在此过程中减少了两个字节。
Glen O

3

JavaScript(ES6),91

递归gcd,迭代主函数。没那么快。

通常的注意事项:在任何符合EcmaScript 6的浏览器上测试运行该代码段(特别是不是Chrome而不是MSIE。我在Firefox上进行了测试,Safari 9可以运行)

F=m=>{
  for(G=(a,b)=>b?G(b,a%b):a,o=[],p=7,n=1;m;d>1&&(o.push(d),--m))
    p+=d=G(++n,p);
  return o
}

O.innerHTML=F(+I.value)
<input id=I value=10><button onclick='O.innerHTML=F(+I.value)'>-></button>
<pre id=O></pre>


3

Haskell,74 71 66字节

f=($filter(>1)$tail>>=zipWith(-)$scanl(\x->(x+).gcd x)7[2..]).take

在这里使用了技巧:https : //codegolf.stackexchange.com/a/39730/43318,并且没有意义。

(上一个:71个字节)

a=scanl(\x->(x+).gcd x)7[2..]
f m=take m$filter(>1)$zipWith(-)(tail a)a

首先确定a的序列,然后求和。

(上一个:74个字节)

f m=take m$filter(>1)$map snd$scanl(\(x,d)->(\y->(x+y,y)).gcd x)(7,1)[2..]

标准列表函数,以及lambda函数的巧妙使用。请注意,此字节比最明显的字节短1个字节

g m=take m$filter(>1)$map snd$scanl(\(x,d)n->(x+gcd x n,gcd x n))(7,1)[2..]

如果不计入进口量,我可以将其降至66。

import Data.List
h m=take m$filter(>1)$snd$mapAccumL(\x->(\y->(x+y,y)).gcd x)7[2..]

3

PARI / GP,60字节

a(n)=a=7;i=1;while(n,if(1<d=gcd(i+=1,a),n-=1;print(d));a+=d)

从定义a(n)-a(n-1)= gcd(n,a(n-1))或多或少直接获得

输出为a(20)

5
3
11
3
23
3
47
3
5
3
101
3
7
11
3
13
233
3
467
3

2

C ++,193个 182 180 172字节

感谢@Jakube-在输出上保存了8个字节。

int g(int a,int b){return a==b?a:a>b?g(b,a-b):g(a,b-a);}void f(int *r,int n){int m=1,i=0,a=7,b;while(i<n){b=g(a,++m);if(b>1){r[i]=b;++i;}a+=b;}}int main(){int r[6];f(r,6);}

您可以通过定义一个函数来节省一些字节,该函数f返回一个包含结果的数组。这样,您可以删除包含,scanf和打印件。
2015年

2

Mathematica,59个字节

For[i=j=1;a=7,i<=#,,d=GCD[++j,a];If[d>1,Print@d;i++];a+=d]&
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.