自然発生の素数ジェネレーター


42

素数生成関数は非常に多数あります。それらのほとんどすべてが構築されており、エラトステネスのふるい、メビウス関数またはウィルソンの定理に基づいており、実際に計算することは一般的に実行不可能です。しかし、非常に簡単な構造を持ち、偶然発見されたジェネレーターもあります。

2003年、スティーブンウルフラムは、NKSサマースクールでのライブコンピューター実験で、ネストされた再帰方程式のクラスを調査しました。マシュー・フランクの周りの人々のグループが追加の実験を追跡し、単純な再発の興味深い特性を発見しました

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–3)/2結局のところ、素数pは連続した1の後にのみ現れます。それでも、この素数ジェネレータを実装するのはあなたの仕事です。

チャレンジ:

nシーケンスの最初の要素A137613(1のないシーケンス)を出力する関数またはプログラムを作成します。入力番号はn >= 0、STDIN、コマンドライン引数、プロンプトまたは関数引数を介して読み取ることができます。n読み取り可能な形式で最初の要素をSTDOUTに出力するか、これらの値を含む配列またはリストを返します。

これはコードゴルフです。したがって、最短のコードが優先されます。

リーダーボード:

これは、通常のリーダーボードと言語ごとの勝者の概要の両方を生成するスタックスニペットです。回答が表示されるようにするには、次のマークダウンテンプレートを使用して、見出しから回答を開始してください。

# 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つの文字を削除しているので//)、あなたの提出でそれを説明してください。誰かがあなたに同意しない場合は、いつでも投稿を編集できます。
ジャクベ

回答:



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するの?副次的な質問:ベータ版を含むPythonの改訂履歴のドキュメントはどこにありますか?編集:気にしないで、改訂履歴の下部にあります。
mbomb007

@ mbomb007以来x >= 11%x0を返し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

うわー、完璧な8 k、いい:D
ベータ崩壊

1
n<2代わりに使用しますn==1。また、後方ではなく前方を見る場合、i=1and x=a(i)-a(i+=1)、and、println(-x)およびand -x>1を使用して否定性を修正することにより、の個別の増分が不要になりますi。そして、3バイト>=ですが、2は...ですが、... n<1||()ではなくn>=1&&()...を使用することができますが、そもそも必要ではありません(条件を削除し、nが1未満になることはありません)。また、a(n)を定義するときに、最も外側のブラケットは必要ありません。これらの変更により、少なくとも97バイトになります。
グレン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
イスマエルミゲル

1
はい、カウントされます。ただし、その改行は削除できます。コードサイズのカウント方法に応じて、1〜2バイト節約できます。
イスマエルミゲル

1
マイナーな改良:使用<$j<=$argv[1](印刷物1は、あまりにも多くの)(-1)。ままに$e初期化されていない、使用する$e+7代わりに(-3)。のfor(;;)代わりにwhile()使用し、事前および事後式を使用します(-2)。置き換えるecho$t.' ';$j++$j+=print"$t "、ブラケットをドロップ(-3)。置き換えるif($t>1)2>$t||(-2)。への割り当てを$t条件付きと組み合わせ、||for orに切り替えて、括弧(-5)をドロップします。移動$argv[1]$j、増分に式全体を移動させるfor条件(-2)。(-3)に変更>=$j+=print-=printます。ステップバイステップ:codepad.org/s6LNSPSM
primo

1
@primo良い説明をありがとう!そんなことができるとは知らなかった。
-jrenk

1
さらにいくつか:(-2)$e+7と組み合わせ$e+=$tます。ままに$i初期化されていない、使用する~++$i代わりに(-3)。codepad.org/fDIImajp
primo

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

2
Pythのバグである@ Sp3000。プルリクエストを送信します。
マルティセン

バグが見つかり修正されました-githubがDDoSされなくなると、パッチが実装されます。
isaacg

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-エラーが表示されると思います。簡単に修正。プロセスで2バイト削り取られました。
グレンO

3

JavaScript(ES6)、91

再帰gcd、反復メイン関数。そんなに早くない。

通常のメモ:EcmaScript 6準拠のブラウザーでスニペットを実行してテストします(特にMSIEではなくChromeを使用します。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..]

標準リスト関数、およびラムダ関数の巧妙な使用。これはより明白なものよりも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結果を含む配列を返すfunctionを定義することで、おそらく数バイトを節約できます。この方法で、include、scanf、およびprintを削除できます。
ジャクベ

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.