最も効率的かつ最短のコードでの最初のn個の素数のリスト[非公開]


27

ルールは簡単です:

  • 最初のn個の素数は、(以下にプライムしないN)、標準出力に出力されなければならない(素数コード内で生成されるべきである)改行で区切ら
  • プライムは、組み込み関数またはライブラリを介して生成することはできません。つまり、prime = get_nth_prime(n)、is_a_prime(number)、factorlist = list_all_factors(number)などの組み込み関数またはライブラリ関数の使用はあまり創造的ではありません。
  • スコアリング-たとえば、スコア = f([コード内の文字数])、Of(n))はアルゴリズムの複雑さを定義します。nは検出した素数の数です。したがって、たとえば、O(n ^ 2)の複雑さを持つ300文字のコードがある場合、スコアは300 ^ 2 = 90000でO(n * ln(n))を持つ300文字の場合、スコアは300 * 5.7 = 1711.13(簡単にするため、すべてのログを自然なログと仮定しましょう)

  • 既存のプログラミング言語を使用して、最低スコアを獲得

編集: O(f(n))の「n」が何であるかについての混乱のため、問題は「最初の1000000素数」の検索から「最初のn個の素数」に変更されました、nは見つける素数の数です(素数の検索はここでの問題と問題の複雑さは、見つかった素数の数に依存します)

注:複雑さの混乱を明確にするために、「n」が見つけた素数で、「N」が見つかったn番目の素数である場合、nに関する複雑さはNとNは同等ではない、つまりO(f(n))! = O(f(N)) as、f(N)!= constant * f(n)and N!= constant * n、n番目の素関数は線形ではないことがわかっているので、素数の複雑さは、「n」で簡単に表現できる必要があります。

Kibbeeが指摘したように、このサイトにアクセスしてソリューションを確認できます(ここに、古いgoogleドキュメントリストがあります)

これらをソリューションに含めてください-

  • プログラムの複雑さ(些細でない場合は基本的な分析を含む)

  • コードの文字長

  • 最終的に計算されたスコア

これは私の最初のCodeGolfの質問です。上記のルールに間違いや抜け穴がある場合は、指摘してください。


5
これはcodegolf.stackexchange.com/questions/5977/…と非常によく似ています
ガレス

2
その1つ1[\p:i.78498に対する私の答えはこれに対する私の答えでした1[\p:i.1000000。Jの内部素数アルゴリズムがO(n ^ 2)であると仮定しても、私のスコアはまだ196にすぎません。–
Gareth

2
複雑さを適切に計算できる人はいないようです。n素数の数なのか最大の素数なのかについては混乱があり、誰もが範囲内の数値の加算0..nO(logn)であり、乗算と除算がさらに高価であるという事実を無視しています。アルゴリズムの例とその正確な複雑さを示すことをお勧めします。
ウゴレン

3
kビット数に対する現在最もよく知られている素数性テストはO-tilde(k^6)です。これO-tilde(n ln n (ln(n ln n))^6)は、問題の一部を誤解したよりも実行時間が優れていると主張する人がいるという意味につながります。O-tildeスコアリングで複雑さをどのように処理するかについての質問。
ピーターテイラー

2
O(n)は、複雑さの点ではO(kn)(定数kの場合)と同等ですが、スコアの点ではそうではないことを誰も指摘していません。たとえば、私の複雑さがO(n ^ 10)であるとします。これはO(n ^ 10 * 1E-308)と同等であり、ひどい複雑さを持つ巨大なプログラムでまだ挑戦するかもしれません。
JDL

回答:


10

Python(129文字、O(n * log log n)、スコア203.948)

エラトステネスのふるいは行くべき道だと思います。非常にシンプルで比較的高速です。

N=15485864
a=[1]*N
x=xrange
for i in x(2,3936):
 if a[i]:
  for j in x(i*i,N,i):a[j]=0
print [i for i in x(len(a))if a[i]==1][2:]

以前からの改善されたコード。

Pythonは(191 156 152文字、O(N *ログログn)は(?)、(252.620スコア?))

複雑さを計算することはまったくできません。これは、私ができる最善の近似です。

from math import log as l
n=input()
N=n*int(l(n)+l(l(n)))
a=range(2,N)
for i in range(int(n**.5)+1):
 a=filter(lambda x:x%a[i] or x==a[i],a)
print a[:n]

n*int(l(n)+l(l(n)))あるトップの境界n番目の素数。


1
複雑さ(およびスコア)の計算は上限に基づいていますがn、素数の数には基づいていません。したがって、スコアはより高くなければならないと思います。上記の私のコメントをご覧ください。
ハワード

上限n?あれは何でしょう?
beary605

ここでの上限はN=15485864です。に基づく複雑度の計算ではn=1000000N=n*log(n)(素数の密度のため)と言うことができます。
ウゴレン

スコアを修正する必要がある場合は、スコアを修正してください。スコアリングシステムについて十分に理解していません。
beary605

@ beary605問題を修正して最初のn個の素数を見つけても大丈夫でしょうか?それは複雑で多くの混乱を解決し、どのようなN O(F(N))であるだろう
オプティマス

7

Haskell、n ^ 1.1の経験的成長率、89文字、スコア139(?)

GHCiプロンプトで使用する一般ライブラリが以前にロードされている場合、次のように動作します。n番目の素数、1ベースを印刷します。

let s=3:minus[5,7..](unionAll[[p*p,p*p+2*p..]|p<-s])in getLine>>=(print.((0:2:s)!!).read)

これは、順序付きリスト用の汎用ライブラリを使用した、エラトステネスの無制限のふるいです。100,000〜200,000素数間の経験的複雑さO(n^1.1)。に適合 O(n*log(n)*log(log n))

複雑さの推定について

100kおよび200k素数の実行時間を測定し、計算logBase 2 (t2/t1)しましたn^1.09。定義g n = n*log n*log(log n)、計算がlogBase 2 (g 200000 / g 100000)できますn^1.12

その後、89**1.1 = 139、もののg(89) = 600。--- (?)

スコアリングには、複雑度関数自体の代わりに推定成長率を使用する必要があるようです。たとえば、g2 n = n*((log n)**2)*log(log n)はよりもはるかに優れていますn**1.5が、100文字の場合、2つのスコアはそれぞれ3239とのスコアになり1000ます。これは正しくありません。200k / 100k範囲の推定値はlogBase 2 (g2 200000 / g2 100000) = 1.2、したがって、のスコアを与え100**1.2 = 251ます。

また、すべての素数を出力するのではなく、n番目の素数だけを出力しようとします。

インポートなし、240文字。n ^ 1.15の経験的成長率、スコア546。

main=getLine>>=(print.s.read)
s n=let s=3:g 5(a[[p*p,p*p+2*p..]|p<-s])in(0:2:s)!!n
a((x:s):t)=x:u s(a$p t)
p((x:s):r:t)=(x:u s r):p t
g k s@(x:t)|k<x=k:g(k+2)s|True=g(k+2)t
u a@(x:r)b@(y:t)=case(compare x y)of LT->x:u r b;EQ->x:u r t;GT->y:u a t

5

Haskell、72 89文字、O(n ^ 2)、スコア7921

文字数あたりの最高スコアが勝ちますか?最初のN向けに修正しました。また、電卓を使用できないようですので、私のスコアは思ったほどひどく悪くはありません。(以下のソースにある基本的な試験部門の複雑さを使用)。

あたりとしてウィルネス以下(実際にREPLに依存しています)フルHaskellのプログラムではありません。以下は、疑似ふるいを使用したより完全なプログラムです(インポートでは実際に文字が保存されますが、コードゴルフではインポートが嫌いです)。

main=getLine>>= \x->print.take(read x).(let s(x:y)=x:s(filter((>0).(`mod`x))y)in s)$[2..]

このバージョンは間違いなく(n ^ 2)です。アルゴリズムは、ここに見られるように、単純な「ふるい」のゴルフバージョンです 。Oldghci 1ライナー

getLine>>= \x->print.take(read x)$Data.List.nubBy(\x y->x`mod`y==0)[2..]

リンク先のライブラリは非常に優れているため、古い不正行為の答えを残します。

print$take(10^6)Data.Numbers.Primes.primes

実装と時間の複雑さのリンクについては、こちらをご覧ください。残念ながら、ホイールにはlog(n)のルックアップ時間があり、要因によって速度が低下します。


•組み込み関数またはライブラリを介してプリムを生成できません
beary605

あなたが合うよう@walpen I'am申し訳ありませんが、私は通知せずにルールを変更し、変更を加えてください
オプティマス

複雑さはO((n ln n)^ 1.5 ln(n ln n)^ 0.585)のようなものではないでしょうか?(またはO((n ln n)^ 1.5 ln(n ln n))Haskellが唐津ではなく、単純な除算を使用する場合)
ピーターテイラー

いいえ、それは私に恐ろしいスコアを与えるからです:/。しかし、私はあなたが正しいと確信しています。それはちょうど試験部門のように見えました、そしてそれは試験部門の時間の複雑さです(おそらく、間違ったソースの私の貧しい読書理解によると)それを選びました。ここでは、スコアをNaNと呼びます。これは安全なようです。
walpen

私は(私のHaskellは無視できますが、SMLでそれを行うのが自然であることを知っています...)あなたはより小さい素数による試行除算をしているだけであり、その場合、Pの試行除算はO( P ^ 0.5 / ln P)除算。ただし、Pにkビットがある場合、除算にはO(k ^ 1.585)(唐葉)またはO(k ^ 2)(ナイーブ)時間がかかり、O(n lg n)の長さO(ln( n lg n))ビット。
ピーターテイラー

5

C#、447文字、バイト452、スコア?

using System;namespace PrimeNumbers{class C{static void GN(ulong n){ulong primes=0;for (ulong i=0;i<(n*3);i++){if(IP(i)==true){primes++;if(primes==n){Console.WriteLine(i);}}}}static bool IP(ulong n){if(n<=3){return n>1;}else if (n%2==0||n%3==0){return false;}for(ulong i=5;i*i<=n;i+=6){if(n%i==0||n%(i+2)==0){return false;}}return true;}static void Main(string[] args){ulong n=Convert.ToUInt64(Console.ReadLine());for(ulong i=0;i<n;i++){GN(i);}}}}

scriptcs Variant、381文字、385バイト、スコア?

using System;static void GetN(ulong n){ulong primes=0;for (ulong i=0;i<(n*500);i++){if(IsPrime(i)==true){primes++;if(primes==n){Console.WriteLine(i);}}}}public static bool IsPrime(ulong n){if(n<=3){return n>1;}else if (n%2==0||n%3==0){return false;}for(ulong i=5;i*i<=n;i+=6){if(n%i==0||n%(i+2)==0){return false;}}return true;}ulong n=Convert.ToUInt64(Console.ReadLine());for(ulong i=0;i<n;i++){GetN(i);}

scriptcsをインストールすると、実行できます。

PS Vimでこれを書いた :D


2
不要な空白を削除することで、一部の文字を保存できます。たとえば、=and <記号の前後に空白を入れる必要はありません。また、このコードのバイトと文字に違いはないと思います。548文字と548バイトです。
ProgramFOX

2
ああ、これが私の最初のCodeGolfです!
XiKuuKy

4

GolfScript(45文字、スコアは〜7708と主張)

~[]2{..3${1$\%!}?={.@\+\}{;}if)1$,3$<}do;\;n*

これは素数による単純な試行分割を行います。Rubyの最先端に近い場合(つまり1.9.3.0を使用)、算術演算はToom-Cook 3乗算を使用するため、試行除算はO(n ^ 1.465)であり、除算の総コストはO((n ln n)^1.5 ln (n ln n)^0.465) = O(n^1.5 (ln n)^1.965)†です。ただし、GolfScriptでは、配列に要素を追加するには配列をコピーする必要があります。私はこれを最適化して、新しい素数が見つかったときにのみ素数のリストをコピーするようにしnました。各コピー操作はO(n)サイズO(ln(n ln n)) = O(ln n)†のアイテムであり、を与えO(n^2 ln n)ます。

そして、これは、男の子と女の子で、GolfScriptが本格的なプログラミングではなくゴルフに使用される理由です。

O(ln (n ln n)) = O(ln n + ln ln n) = O(ln n)。さまざまな投稿にコメントする前にこれを見つけたはずです...


4

私のテキストエディタでもこれを実行できます。

Vim:143キーストローク(115アクション):O(n ^ 2 * log(n)):スコア:101485.21

提出:

qpqqdqA^V^Ayyp<Esc>3h"aC@a<Esc>0C1<Esc>@"ddmpqdmd"bywo^Ra ^Rb 0 0 `pj@p ^Ra 0 ^R=@a%@b<Enter> `pdd@p 0 `dj@d<Esc>0*w*wyiWdd@0qqpmp"aywgg@dqgg@p

入力:Nは空白のドキュメントの最初の行にある必要があります。これが終了すると、2からNまでの各素数は別々の行になります。

コマンドの実行:

最初に、キャレットが前に付いているコマンドは、Ctrlキーを押しながら次の文字を入力する必要があることに注意してください(例:^ V is Ctrl-vおよび^ R is Ctrl-r)。

これにより、@ a、@ b、@ d、および@pレジスタのすべてが上書きされます。

これはqコマンドを使用するため、マクロに配置することはできません。ただし、実行するためのヒントを次に示します。

  • qpqqdq レジスタをクリアするだけ
  • A^V^Ayyp<Esc>3h"aC@a<Esc>0C1<Esc>@"dd2からN + 1までの数字のリストを作成します。これは2つの主要な部分の間の休憩なので、これが完了したら、再度行う必要はありません。
  • mpqdmd"bywo^Ra ^Rb 0 0 `pj@p ^Ra 0 ^R=@a%@b<Enter> `pdd@p 0 `dj@d<Esc>0*w*wyiWdd@0qqpmp"aywgg@dqgg@p一度に入力する必要があります。何かを台無しにする可能性があるため、バックスペースを避けてください。
    • 間違えた場合は、入力してqdqqpqからこの行を再試行してください。

大きなNの場合、これは非常に遅いです。N = 5000の実行には約27分かかりました。自分が警告したと考えてください。

アルゴリズム:

これは素数を見つけるために基本的な再帰アルゴリズムを使用します。1からAまでのすべての素数のリストが与えられた場合、素数のリストのいずれの数でも割り切れない場合、A + 1は素数になります。A = 2から開始し、見つかったときに素数をリストに追加します。N回の再帰後、リストにはNまでのすべての素数が含まれます。

複雑

このアルゴリズムの複雑さはO(nN)です。ここで、Nは入力数、nはNまでの素数の数です。各再帰はn個の数をテストし、N回の再帰が実行され、O(nN)が得られます。

ただし、N〜n * log(n)、O(n 2 * log(n))(https://en.wikipedia.org/wiki/Prime_number_theorem#Approximations_for_the_nth_prime_number)として最終的な複雑さを与えます

説明

プログラムフローをvimコマンドから識別するのは簡単ではないため、同じフローに従ってPythonで書き直しました。Vimコードと同様に、Pythonコードは最後に到達するとエラーになります。Pythonは、あまりにも多くの再帰を好みません。N> 150程度でこのコードを試すと、最大再帰深度に達します。

N = 20
primes = range(2, N+1)

# Python needs these defined.
mark_p = b = a = -1

# Check new number for factors. 
# This macro could be wrapped up in @d, but it saves space to leave it separate.
def p():
    global mark_d, mark_p, primes, a
    mark_d = 0
    print(primes)
    a = primes[mark_p]
    d()      

# Checks factor and determine what to do next
def d():
    global mark_d, mark_p, a, b, primes
    b = primes[mark_d]
    if(a == b): # Number is prime, check the next number
        mark_p += 1
        p()
    else:
        if(a%b == 0): # Number is not prime, delete it and check next number
            del(primes[mark_p])
            p()
        else: # Number might be prime, try next possible factor
            mark_d += 1
            d()

mark_p = 0 #Start at first number         
p()

次に、実際のキーストロークを分解します!

  • qpqqdq@dおよび@pレジスタをクリアします。これにより、これらの再帰マクロを設定するときに何も実行されなくなります。

  • A^V^Ayyp<Esc>3h"aC@a<Esc>0C1<Esc>@"dd入力を2からN + 1までの数字のリストに変換します。N + 1エントリは、@ dマクロを設定する副作用として削除されます。

    • 具体的には、数値をインクリメントするマクロを書き込み、次の行にコピーしてから、1を書き込み、このマクロをN回実行します。
  • mpqdmd"bywo^Ra ^Rb 0 0 `pj@p ^Ra 0 ^R=@a%@b<Enter> `pdd@p 0 `dj@d<Esc>0*w*wyiWdd@0q上記のd()関数を実装する@dマクロを記述します。「if」ステートメントは、Vimで実装するのに興味深いものです。検索演算子*を使用することにより、特定のパスを選択することができます。コマンドをさらに分解すると、

    • mpqdここでpマークを設定し、@ dマクロの記録を開始します。pマークを設定する必要があるため、この実行時にジャンプする既知のポイントがあります。
    • o^Ra ^Rb 0 0 `pj@p ^Ra 0 ^R=@a%@b<Enter> `pdd@p 0 `dj@d<Esc> if / elseステートメントテキストを書き込みます
    • 0*w*wyiWdd@0 実際にifステートメントを実行します。
    • このコマンドを実行する前に、行には @a @b 0 0 `pj@p @a 0 (@a%@b) `pdd@p 0 `dj@d
    • 0 カーソルを行頭に移動します
    • *w*w 次に実行するコードにカーソルを移動します

      1. @a == @bの場合、つまり`pj@p、@ aの次の番号に移動し、その番号で@pを実行します。
      2. @a!= @bおよび@ a%@ b == 0の場合、つまり`pdd@p、現在の番号@aを削除し、次の番号で@pを実行します。
      3. @a!= @bおよび@ a %% b!= 0の場合、つまり、@ b `dj@dの次の数値をチェックして、@ a の因子であるかどうかを確認します。
    • yiWdd@0 コマンドを0レジスタにヤンクし、行を削除してコマンドを実行します

    • q @dマクロの記録を終了します
  • これが最初に実行されると、`pdd@pコマンドが実行され、N + 1行が削除されます。

  • qpmp"aywgg@dq @pマクロを書き込みます。このマクロは、カーソルの下の数値を保存し、最初のエントリに移動して、そのエントリに対して@dを実行します。

  • gg@p 実際に@pを実行して、ファイル全体を反復処理します。


3

QBASIC、98文字、複雑度N Sqrt(N)、スコア970

I=1
A:I=I+2
FOR J=2 TO I^.5
    IF I MOD J=0 THEN GOTO A
NEXT
?I
K=K+1
IF K=1e6 THEN GOTO B
GOTO A
B:

私は、その、今、私はノー通知のために申し訳ありませんが、最初の「n」は素数を見つけ、問題文のビット変更した
オプティマス

このプログラムの「ソース内」入力を想定できると思います。すなわち、入力は直後の数字ですIF K=(したがって、プログラムの長さには数字が含まれません)。現状では、プログラムは2を含まない最初のn個の素数を出力します。これは?2、先頭に追加し、に変更K=...することで修正できますK=...-1。プログラムはまた、外のスペースを取ることによってビットをgolfedすることができJ=2 TOJ=0 THENK=...-1 THEN、およびインデントを削除することによって。この結果、96文字のプログラムになると思います。
解像度

3

Scala 263文字

新しい要件に合わせて更新されました。コードの25%は、以下の素数を計算するための合理的な上限を見つけることに対処しています。

object P extends App{
def c(M:Int)={
val p=collection.mutable.BitSet(M+1)
p(2)=true
(3 to M+1 by 2).map(p(_)=true)
for(i<-p){
var j=2*i;
while(j<M){
if(p(j))p(j)=false
j+=i}
}
p
}
val i=args(0).toInt
println(c(((math.log(i)*i*1.3)toInt)).take(i).mkString("\n"))
}

ふるいももらった。

以下は、分析のために計算されていない計算コストの実証的テストです。

object PrimesTo extends App{
    var cnt=0
    def c(M:Int)={
        val p=(false::false::true::List.range(3,M+1).map(_%2!=0)).toArray
        for (i <- List.range (3, M, 2)
            if (p (i))) {
                var j=2*i;
                while (j < M) {
                    cnt+=1
                    if (p (j)) 
                        p(j)=false
                    j+=i}
            }
        (1 to M).filter (x => p (x))
    }
    val i = args(0).toInt
    /*
        To get the number x with i primes below, it is nearly ln(x)*x. For small numbers 
        we need a correction factor 1.13, and to avoid a bigger factor for very small 
        numbers we add 666 as an upper bound.
    */
    val x = (math.log(i)*i*1.13).toInt+666
    println (c(x).take (i).mkString("\n"))
    System.err.println (x + "\tcount: " + cnt)
}
for n in {1..5} ; do i=$((10**$n)); scala -J-Xmx768M P $i ; done 

次のカウントにつながります:

List (960, 1766, 15127, 217099, 2988966)

スコアの計算方法がわかりません。さらに5文字を書く価値はありますか?

scala> List(4, 25, 168, 1229, 9592, 78498, 664579, 5761455, 50847534).map(x=>(math.log(x)*x*1.13).toInt+666) 
res42: List[Int] = List(672, 756, 1638, 10545, 100045, 1000419, 10068909, 101346800, 1019549994)

scala> List(4, 25, 168, 1229, 9592, 78498, 664579, 5761455, 50847534).map(x=>(math.log(x)*x*1.3)toInt) 
res43: List[Int] = List(7, 104, 1119, 11365, 114329, 1150158, 11582935, 116592898, 1172932855)

nが大きくなると、その範囲で計算が約16%減少しますが、スコアの式については、定数因子を考慮しませんか?

新しいBig-Oに関する考慮事項:

1 000、10000、100,000素数などを見つけるには、実行中の外側のループを決定する素数x =>(math.log(x)* x * 1.3の密度に関する式を使用します。

したがって、1から6 => NPrimes(10 ^ i)の値iの場合、外側のループの9399、133768 ...倍を実行します。

このO関数は、Peter Taylorのコメントの助けを借りて反復的に見つけました。PeterTaylorは、1.01ではなく、1.5を提案した指数のはるかに高い値を提案しました。

def O(n:Int) = (math.pow((n * math.log (n)), 1.01)).toLong

O:(n:Int)Long

val ns = List(10, 100, 1000, 10000, 100000, 1000*1000).map(x=>(math.log(x)*x*1.3)toInt).map(O) 

ns:List [Long] = List(102、4152、91532、1612894、25192460、364664351)

 That's the list of upper values, to find primes below (since my algorithm has to know this value before it has to estimate it), send through the O-function, to find similar quotients for moving from 100 to 1000 to 10000 primes and so on: 

(ns.head /: ns.tail)((a, b) => {println (b*1.0/a); b})
40.705882352941174
22.045279383429673
17.62109426211598
15.619414543051187
14.47513863274964
13.73425213148954

1.01を指数として使用する場合、これは商です。カウンターが経験的に見つけたものは次のとおりです。

ns: Array[Int] = Array(1628, 2929, 23583, 321898, 4291625, 54289190, 660847317)

(ns.head /: ns.tail)((a, b) => {println (b*1.0/a); b})
1.799140049140049
8.051553431205189
13.649578085909342
13.332251210010625
12.65003116535112
12.172723833234572

最初の2つの値は外れ値です。これは、小さな値(最大1000)の推定式を常に修正しているためです。

1.5のPeter Taylorsの提案では、次のようになります。

245.2396265560166
98.8566987153728
70.8831374743478
59.26104390040363
52.92941829568069
48.956394784317816

今私の価値で私は得る:

O(263)
res85: Long = 1576

しかし、O関数を使用して観測値にどれだけ近づけるかはわかりません。


申し訳ありませんが、私は(私は必ずあなたのソリューションは、あまり変化はないよ)、複雑に関連するいくつかの曖昧さを減らすために、問題文のいくつかの変更を加えた
オプティマス

これは実質的に素数による試行分割です。内側のループを通過する回数はO(M^1.5 / ln M)であり、毎回あなたがO(ln M)作業(追加)するので、全体としてはO(M^1.5) = O((n ln n)^1.5)です。
ピーターテイラー

^ 1.5の代わりに^ 1.02を使用するdef O(n:Int) = (math.pow((n * math.log (n)), 1.02)).toLongと、カウンターで経験的に見つかった値にはるかに近づきます。調査結果を投稿に挿入します。
ユーザー不明

3

Ruby 66文字、O(n ^ 2)スコア-4356

lazyRuby 2.0以降で使用でき1.0/0、無限の範囲を取得するためのクールなトリックです。

(2..(1.0/0)).lazy.select{|i|!(2...i).any?{|j|i%j==0}}.take(n).to_a

1
1文字を(2..(1.0/0)).lazy.select{|i|!(2...i).any?{|j|i%j<1}}.take(n).to_a
-Qqwy

または:(これにより、ソリューションの効率は低下しますが、O(n²)の上限は変更されません)(2..(1.0/0)).lazy.select{|i|(2..i).one?{|j|i%j<1}}.take(n).to_a。これにより、さらに2つのキャラクターが削られます。
Qqwy

それをうまく変更する(2..(1.0/0)).lazy.select{|i|!(2...i).any?{|j|i%j<1}}.first(n)と、61文字になります。
リッチー

2

Ruby、84文字、84バイト、スコア?

これはおそらくこれらの部品には少し初心者ですが、私はそれをやって楽しい時間を過ごしました。f(見つかった素数)がに一致するまでループするだけnで、必要な素数の数が見つかります。

楽しい部分は、ループごとに、検査対象の数より2から1少ない配列を作成することです。次に、配列内の各要素を元の数値と要素の係数にマッピングし、結果のいずれかがゼロであるかどうかを確認します。

また、私はそれを獲得する方法がわかりません。

更新

コードが圧縮され、(完全に任意の)値が含まれています n

n,f,i=5**5,0,2
until f==n;f+=1;p i if !(2...i).to_a.map{|j|i%j}.include?(0);i+=1;end

元の

f, i = 0, 2
until f == n
  (f += 1; p i) if !(2...i).to_a.map{|j| i % j}.include?(0)
  i += 1
end

i += 1ビットおよびuntilループは、ソートの改善のための領域として私に飛び出しのですが、この曲に私は、ソートこだわっのです。とにかく、考えるのは楽しかったです。


2

Scala、124文字

object Q extends App{Stream.from(2).filter(p=>(2 to p)takeWhile(i=>i*i<=p)forall{p%_!= 0})take(args(0)toInt)foreach println}

平方根までの単純な試行分割。したがって、複雑さはO(n ^(1.5 + epsilon))でなければなりません

124 ^ 1.5 <1381、それが私のスコアでしょうか?


1

Perl-94文字、O(n log(n))-スコア:427

perl -wle '$n=1;$t=1;while($n<$ARGV[0]){$t++;if((1x$t)!~/^1?$|^(11+?)\1+$/){print $t;$n++;}}'

Python-113文字

import re
z = int(input())
n=1
t=1
while n<z:
    t+=1
    if not re.match(r'^1?$|^(11+?)\1+$',"1"*t):
        print t
        n+=1

1

AWK、96 86バイト

字幕:ママ見て!追加といくつかの簿記のみ!

ファイルfsoe3.awk

{for(n=2;l<$1;){if(n in L)p=L[n]
else{print p=n;l++}
for(N=p+n++;N in L;)N+=p
L[N]=p}}

実行:

$ awk -f fsoe3.awk <<< 5
2
3
5
7
11
$ awk -f fsoe3.awk <<< 1000 | wc -l
1000

BASH、133バイト

ファイルx.bash

a=2
while((l<$1));do if((b[a]))
then((c=b[a]));else((c=a,l++));echo $a;fi;((d=a+c))
while((b[d]));do((d+=c));done
((b[d]=c,a++));done

実行:

$ bash x.bash 5
2
3
5
7
11
$ bash x.bash 1000 | wc -l
1000

素数は、既に見つかった素数を「正の整数のテープ」にジャンプさせることで計算されます。基本的には、シリアル化されたエラトステネスのふるいです。

from time import time as t

L = {}
n = 2
l = 0

t0=t()

while l<1000000:

        if n in L:
                P = L[n]
        else:
                P = n
                l += 1
                print t()-t0

        m = n+P
        while m in L:
                m += P
        L[m] = P

        n += 1

...はPythonの同じアルゴリズムでlあり、素数自体ではなく-th個の素数が見つかった時刻を出力します。

で出力をプロットするgnuplotと、次の結果が得られます。

ここに画像の説明を入力してください

ジャンプは、おそらくバッファされたデータをディスクに書き込むためのファイルI / Oの遅延と関係があります...

はるかに多くの素数を使用して検索すると、システムに依存する遅延がゲームに追加されます。たとえば、「正の整数のテープ」を表す配列が連続的に成長し、遅かれ早かれ、すべてのコンピューターがより多くのRAM(またはスワップ)を必要とするようになります。

...そのため、実験データを見て複雑さのアイデアを得ることはあまり役に立ちません... :-(


n素数を見つけるために必要な追加を数えます:

cells = {}
current = 2
found = 0

additons = 0

while found < 10000000:

        if current in cells:
                candidate = cells[current]
                del cells[current] # the seen part is irrelevant
        else:
                candidate = current
                found += 1 ; additons += 1
                print additons

        destination = current + candidate ; additons += 1
        while destination in cells:
                destination += candidate ; additons += 1
        cells[destination] = candidate

        current += 1 ; additons += 1

ここに画像の説明を入力してください


これらのグラフをどのように作成しましたか?

1
Gnuplotset term xterm、その後のスクリーンショットxterm(忘れられた機能におそらく近い)のグラフィックス・ウィンドウ。;-)

0

Scala 121(メインクラスボイラープレートなしの99)

object Q extends App{Stream.from(2).filter{a=>Range(2,a).filter(a%_==0).isEmpty}.take(readLine().toInt).foreach(println)}

0

Python 3、117 106バイト

このソリューションは、数値が素数でない場合に0を出力するため、わずかに簡単ですが、とにかく投稿します。

r=range
for i in[2]+[i*(not 0 in[i%j for j in r(3,int(i**0.5)+1,2)])for i in r(3,int(input()),2)]:print(i)

また、アルゴリズムの複雑さをどのように解決するかわかりません。このため、ダウン投票しないでください。代わりに、素敵になり、私がそれをどのように解決できるかコメントしてください。また、これを短縮する方法を教えてください。


私はあなたが置くことができると思いprint(i)forループと同じ行にとのスペースを削除しin [2]0 if0 in [i%j+1,2)] else
アクロリス

@daHugLennyうわー、どうもありがとう!すぐに投稿を編集します。:-D
0WJYxW9FMN

@daHugLenny万が一効率を計算する方法を知っていますか?
0WJYxW9FMN

いいえ、ごめんなさい。(コメントは少なくとも15文字でなければなりません)
アクロリス

とにかくありがとう。ここで私のプログラムが最短になりました!
0WJYxW9FMN


0

Perl 6、152バイト、O(n log n log(n log n)log(log(n log n))))(?)、9594.79ポイント

このページによると、nまでのすべての素数を見つけるビットの複雑さはO(n log n log log n)です。上記の複雑さは、n番目の素数がn log nに比例するという事実を使用しています。

my \N=+slurp;my \P=N*(N.log+N.log.log);my @a=1 xx P;for 2..P.sqrt ->$i {if @a[$i] {@a[$_*$i]=0 for $i..P/$i}};say $_[1] for (@a Z ^P).grep(*[0])[2..N+1]

資格、資格をWentelでそれをしない
noɥʇʎԀʎzɐɹƆ

申し訳ありませんが、どういう意味ですか?
bb94

報奨金(fiiiiiiiiilerrrrr)について
noɥʇʎԀʎzɐɹƆ

0

Groovy(50バイト)-O(n * sqrt(n))-スコア353.553390593

{[1,2]+(1..it).findAll{x->(2..x**0.5).every{x%it}}​}​

nを取り込んで、1からnまでの素数をすべて出力します。

選択したアルゴリズムは素数n> 2のみを出力するため、最初に1,2を追加する必要があります。

壊す

x%it -割り切れない場合は暗黙の真実性、割り切れる場合は偽り。

(2..x**0.5).every{...}-2からsqrt(x)までのすべての値について、それらが割り切れないことを確認します。これによりtrueを返すには

(1..it).findAll{x->...} -1からnまでのすべての値について、2からsqrt(n)の間で割り切れないという基準に適合するすべてを見つけます。

{[1,2]+...}​ -1と2を追加します。これらは常に素数であり、アルゴリズムでカバーされないためです。


0

ラケット155バイト

(let p((o'(2))(c 3))(cond[(>=(length o)n)(reverse o)][(ormap(λ(x)(= 0(modulo c x)))
(filter(λ(x)(<= x(sqrt c)))o))(p o(add1 c))][(p(cons c o)(add1 c))]))

見つかった素数のリストを保持し、すでに見つかった素数による次の各数の可分性をチェックします。さらに、テスト対象の数の平方根までしかチェックしないため、十分です。

ゴルフをしていない:

(define(nprimes n)
  (let loop ((outl '(2))                   ; outlist having primes being created
             (current 3))                  ; current number being tested
  (cond
    [(>= (length outl) n) (reverse outl)]  ; if n primes found, print outlist.
    [(ormap (λ(x) (= 0 (modulo current x))) ; test if divisible by any previously found prime
            (filter                         ; filter outlist till sqrt of current number
             (λ(x) (<= x (sqrt current)))
             outl))
     (loop outl (add1 current)) ]           ; goto next number without adding to prime list
    [else (loop (cons current outl) (add1 current))] ; add to prime list and go to next number
    )))

テスト:

(nprimes 35)

出力:

'(2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149)

0

awk 45(複雑さN ^ 2)

別のawk、100までの素数はこのように使用します

awk '{for(i=2;i<=sqrt(NR);i++) if(!(NR%i)) next} NR>1' <(seq 100)

コードゴルフのカウント部分は

{for(i=2;i<=sqrt(NR);i++)if(!(NR%i))next}NR>1

スクリプトファイルに入れて、次のように実行できます。 awk -f prime.awk <(seq 100)


0

Javascript、61文字

f=(n,p=2,i=2)=>p%i?f(n,p,++i):i==p&&n--&alert(p)||n&&f(n,++p)

O(n ^ 2)よりも少し悪い場合、nが大きいとスタック領域が不足します。

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