Daftar bilangan prima pertama n paling efisien dan dalam kode terpendek [ditutup]


27

Aturannya sederhana:

  • Pertama n bilangan prima (bukan bilangan prima di bawah n ), harus dicetak ke output standar dipisahkan oleh baris baru (bilangan prima harus dihasilkan dalam kode)
  • bilangan prima tidak dapat dihasilkan oleh fungsi inbuilt atau melalui perpustakaan , yaitu penggunaan fungsi inbuilt atau perpustakaan seperti, prime = get_nth_prime (n), is_a_prime (angka), atau daftar faktor = list_all_factors (angka) tidak akan sangat kreatif.
  • Penilaian - Katakanlah, kita mendefinisikan Skor = f ([jumlah karakter dalam kode]), O ( f (n)) menjadi kompleksitas algoritme Anda di mana n adalah jumlah bilangan prima yang ditemukannya. Jadi misalnya, jika Anda memiliki 300 kode char dengan kompleksitas O (n ^ 2), skor adalah 300 ^ 2 = 90000 , untuk 300 karakter dengan O (n * ln (n)), skor menjadi 300 * 5.7 = 1711.13 ( mari kita anggap semua log menjadi log natural untuk kesederhanaan)

  • Gunakan bahasa pemrograman yang ada, kemenangan skor terendah

Sunting: Masalah telah diubah dari menemukan 'prima pertama 1000000' menjadi 'n primes pertama' karena kebingungan tentang apa 'n' di O (f (n)) adalah, n adalah jumlah bilangan prima yang Anda temukan (menemukan bilangan prima adalah masalah di sini dan kompleksitas masalah tergantung pada jumlah bilangan prima yang ditemukan)

Catatan: untuk memperjelas beberapa kebingungan tentang kompleksitas, jika 'n' adalah jumlah bilangan prima yang Anda temukan dan 'N' adalah bilangan prima ke-n, kompleksitas dalam n adalah dan N tidak setara yaitu O (f (n))! = O (f (N)) sebagai, f (N)! = Konstan * f (n) dan N! = Konstan * n, karena kita tahu bahwa fungsi utama ke-n tidak linier, saya pikir karena kami menemukan 'n' Kompleksitas bilangan prima harus mudah diungkapkan dalam hal 'n'.

Seperti yang ditunjukkan oleh Kibbee, Anda dapat mengunjungi situs ini untuk memverifikasi solusi Anda (di sini , adalah daftar google docs lama)

Harap Sertakan ini dalam solusi Anda -

  • kompleksitas apa yang dimiliki program Anda (termasuk analisis dasar jika tidak sepele)

  • panjang kode karakter

  • skor akhir yang dihitung

Ini adalah Pertanyaan CodeGolf pertama saya, jadi, jika ada kesalahan atau celah dalam aturan di atas, mohon tunjukkan.



2
Jawaban saya untuk yang satu itu adalah 1[\p:i.78498jawaban saya untuk ini 1[\p:i.1000000. Bahkan dengan asumsi bahwa algoritma prime internal J adalah O (n ^ 2) skor saya masih hanya 196.
Gareth

2
Sepertinya tidak ada yang berhasil menghitung kompleksitas mereka dengan benar. Ada kebingungan tentang apakah njumlah bilangan prima atau bilangan prima maksimum, dan semua orang mengabaikan fakta bahwa penambahan bilangan dalam kisaran 0..nitu O(logn), dan penggandaan dan pembagian bahkan lebih mahal. Saya menyarankan Anda memberikan beberapa contoh algoritma beserta kompleksitasnya yang benar.
ugoren

3
Tes primality yang paling dikenal saat ini untuk bilangan k-bit adalah O-tilde(k^6). Ini mengarah pada implikasi bahwa siapa pun yang mengklaim waktu berjalan lebih baik daripada O-tilde(n ln n (ln(n ln n))^6)salah paham beberapa bagian dari masalah; dan untuk pertanyaan bagaimana O-tildekompleksitas harus ditangani dalam penilaian.
Peter Taylor

2
Tidak ada yang menunjukkan, bahwa O (n) setara dengan O (kn) (untuk k konstan) dalam hal kompleksitas, tetapi tidak dalam istilah skor. Sebagai contoh, anggap kompleksitas saya adalah O (n ^ 10). Itu setara dengan O (n ^ 10 * 1E-308), dan saya masih dapat memenangkan tantangan dengan program besar dengan kompleksitas yang mengerikan.
JDL

Jawaban:


10

Python (129 karakter, O (n * log log n), skor 203.948)

Saya akan mengatakan Saringan Eratosthenes adalah cara untuk pergi. Sangat sederhana dan relatif cepat.

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:]

Kode ditingkatkan dari sebelumnya.

Python ( 191 156 152 karakter, O (n * log log n) (?), Skor 252.620 (?))

Saya tidak bisa menghitung kompleksitas sama sekali, ini adalah perkiraan terbaik yang bisa saya berikan.

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)))adalah batas atas dari nbilangan prima th.


1
Perhitungan kompleksitas (dan dengan demikian skor) didasarkan pada batas atas ntetapi tidak pada jumlah bilangan prima. Jadi, saya menganggap skor harus lebih tinggi. Lihat komentar saya di atas.
Howard

Batas atas n? Apa itu?
beary605

Batas atas di sini adalah N=15485864. Untuk perhitungan kompleksitas berdasarkan n=1000000, Anda dapat mengatakan N=n*log(n)(karena kepadatan bilangan prima).
ugoren

Jika skor saya perlu diperbaiki, tolong perbaiki untuk saya, saya masih belum memiliki pemahaman yang baik tentang sistem penilaian.
beary605

@ beary605 apakah akan baik-baik saja jika saya memodifikasi masalah untuk menemukan n primer pertama? yang akan menyelesaikan banyak kebingungan pada kompleksitas dan apa yang ada di O (f (n))
Optimus

7

Haskell, n ^ 1,1 tingkat pertumbuhan empiris, 89 karakter, skor 139 (?)

Berikut ini berfungsi di GHCi prompt ketika perpustakaan umum yang digunakan sudah dimuat sebelumnya. Cetak n th prima, 1 berbasis:

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

Ini adalah saringan Eratosthenes tanpa batas, menggunakan pustaka penggunaan umum untuk daftar yang dipesan. Kompleksitas empiris antara 100.000 dan 200.000 bilangan prima O(n^1.1). Cocok untuk O(n*log(n)*log(log n)).

Tentang estimasi kompleksitas

Saya mengukur waktu berjalan untuk 100k dan 200k bilangan prima, kemudian dihitung logBase 2 (t2/t1), yang menghasilkan n^1.09. Menentukan g n = n*log n*log(log n), menghitung logBase 2 (g 200000 / g 100000)memberi n^1.12.

Lalu 89**1.1 = 139, meskipun g(89) = 600. --- (?)

Tampaknya untuk penilaian laju pertumbuhan diperkirakan harus digunakan alih-alih fungsi kompleksitas itu sendiri. Misalnya, g2 n = n*((log n)**2)*log(log n)jauh lebih baik daripada n**1.5, tetapi untuk 100 karakter keduanya menghasilkan skor 3239dan 1000, masing-masing. Ini tidak mungkin benar. Estimasi pada kisaran 200k / 100k memberi logBase 2 (g2 200000 / g2 100000) = 1.2dan dengan demikian skor 100**1.2 = 251.

Juga, saya tidak berusaha mencetak semua bilangan prima, hanya n perdana ke- saja.

Tanpa impor, 240 karakter. n ^ 1,15 tingkat pertumbuhan empiris, skor 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 karakter, O (n ^ 2), Skor 7921

Skor tertinggi per hitungan char menang benar? Dimodifikasi untuk yang pertama N. Juga saya tampaknya tidak dapat menggunakan kalkulator, jadi skor saya tidak seburuk yang saya kira. (menggunakan kompleksitas untuk pembagian percobaan dasar seperti yang ditemukan dalam sumber di bawah).

Per Will Ness di bawah ini bukanlah program Haskell penuh (itu sebenarnya bergantung pada REPL). Berikut ini adalah program yang lebih lengkap dengan pseudo-saringan (impor sebenarnya menyimpan char, tapi saya tidak suka impor dalam kode golf).

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

Versi ini tidak diragukan lagi (n ^ 2). Algoritma ini hanya versi golf dari naif `` saringan '', seperti yang terlihat di sini Old ghci 1 kapal

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

Meninggalkan jawaban yang lama dan curang karena perpustakaan yang ditautkannya cukup bagus.

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

Lihat di sini untuk implementasi dan tautan untuk kompleksitas waktu. Sayangnya roda memiliki waktu pencarian log (n), memperlambat kita oleh faktor.


• bilangan prima tidak dapat dihasilkan oleh fungsi bawaan atau melalui perpustakaan
beary605

@walpen Maaf, saya memodifikasi aturan tanpa pemberitahuan, silakan lakukan perubahan yang Anda inginkan
Optimus

Bukankah kerumitannya seperti O ((n ln n) ^ 1.5 ln (n ln n) ^ 0.585)? (Atau O ((n ln n) ^ 1,5 ln (n ln n)) jika Haskell menggunakan divisi naif daripada, seperti yang saya duga, Karatsuba)
Peter Taylor

Tidak, karena itu memberi saya skor menghebohkan: /. Tapi saya yakin Anda benar. Itu hanya terlihat seperti pembagian percobaan, dan itulah kompleksitas waktu pembagian percobaan (mungkin, menurut pemahaman bacaan saya yang buruk tentang sumber yang mungkin salah) jadi saya memilih itu. Untuk saat ini saya akan memanggil skor saya NaN, yang tampaknya aman.
walpen

Saya berasumsi (Haskell saya dapat diabaikan, tapi saya tahu bagaimana wajar melakukannya di SML ...) bahwa Anda hanya melakukan pembagian percobaan dengan bilangan prima yang lebih kecil, di mana pembagian kasus percobaan pada P melakukan O ( P ^ 0,5 / ln P) divisi. Tetapi jika P memiliki bit k, pembagian membutuhkan waktu O (k ^ 1.585) (Karatsuba) atau O (k ^ 2) (naif), dan Anda perlu menjalankan melalui O (n lg n) jumlah panjang O (ln ( n lg n)) bit.
Peter Taylor

5

C #, 447 Karakter, Bytes 452, Skor?

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);}}}}

Varian scriptcs, 381 Karakter, 385 Bytes, Nilai?

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);}

Jika Anda menginstal skrip maka Anda dapat menjalankannya.

PS Saya menulis ini di Vim :D


2
Anda dapat menyimpan beberapa karakter dengan menghapus spasi kosong yang tidak perlu. Misalnya, tidak perlu menempatkan spasi putih di sekitar tanda =dan <. Juga, saya tidak berpikir ada perbedaan dalam byte dan karakter untuk kode ini - itu 548 karakter dan 548 byte.
ProgramFOX

2
Oh terima kasih, ini CodeGolf pertamaku!
XiKuuKy

4

GolfScript (45 karakter, skor diklaim ~ 7708)

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

Ini melakukan pembagian percobaan sederhana oleh bilangan prima. Jika mendekati ujung tombak dari Ruby (yaitu menggunakan 1.9.3.0) aritmatika menggunakan perkalian Toom-Cook 3, jadi divisi percobaan adalah O (n ^ 1.465) dan biaya keseluruhan divisi adalah O((n ln n)^1.5 ln (n ln n)^0.465) = O(n^1.5 (ln n)^1.965)†. Namun, dalam GolfScript menambahkan elemen ke array membutuhkan menyalin array. Saya telah mengoptimalkan ini untuk menyalin daftar bilangan prima hanya ketika menemukan bilangan prima baru, sehingga hanya ntotal kali. Setiap operasi penyalinan adalah O(n)item dengan ukuran O(ln(n ln n)) = O(ln n)†, memberiO(n^2 ln n) .

Dan inilah, anak laki-laki dan perempuan, mengapa GolfScript digunakan untuk bermain golf daripada untuk pemrograman serius.

O(ln (n ln n)) = O(ln n + ln ln n) = O(ln n). Saya seharusnya melihat ini sebelum mengomentari berbagai posting ...


4

Ini sangat mudah bahkan editor teks saya dapat melakukan ini!

Vim: 143 penekanan tombol (115 tindakan): O (n ^ 2 * log (n)): Nilai: 101485.21

Pengajuan:

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

Input: N harus di baris pertama dari dokumen kosong. Setelah ini selesai, setiap prime dari 2 ke N akan menjadi baris terpisah.

Menjalankan Perintah:

Pertama, perhatikan bahwa setiap perintah dengan tanda sisipan di depannya berarti Anda harus menahan Ctrl dan mengetik huruf berikutnya (mis. ^ V is Ctrl-vdan ^ R isCtrl-r ).

Ini akan menimpa apa pun di register @a, @b, @d, dan @p Anda.

Karena ini menggunakan qperintah, itu tidak bisa hanya ditempatkan di makro. Namun, berikut adalah beberapa tips untuk menjalankannya.

  • qpqqdq hanya membersihkan register
  • A^V^Ayyp<Esc>3h"aC@a<Esc>0C1<Esc>@"ddakan membuat daftar angka 2 hingga N +1. Ini adalah jeda antara dua bagian utama, jadi setelah ini selesai, Anda tidak perlu melakukannya lagi
  • 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@ptidak perlu diketik sekaligus. Cobalah untuk menghindari backspace karena dapat mengacaukan sesuatu.
    • Jika Anda membuat kesalahan, ketikkan qdqqpqkemudian coba baris ini lagi.

Untuk N besar, ini sangat lambat. Butuh sekitar 27 menit untuk menjalankan N = 5000; anggap dirimu sudah diperingatkan.

Algoritma:

Ini menggunakan algoritma rekursif dasar untuk menemukan bilangan prima. Diberikan daftar semua bilangan prima antara 1 dan A, A + 1 adalah bilangan prima jika tidak dapat dibagi dengan angka-angka dalam daftar bilangan prima. Mulai dari A = 2 dan tambahkan bilangan prima ke daftar saat ditemukan. Setelah N rekursi, daftar akan berisi semua bilangan prima hingga N.

Kompleksitas

Algoritma ini memiliki kompleksitas O (nN), di mana N adalah nomor input dan n adalah jumlah bilangan prima hingga N. Setiap rekursi menguji n angka, dan rekursi N dilakukan, menghasilkan O (nN).

Namun, N ~ n * log (n), memberikan kompleksitas akhir sebagai O (n 2 * log (n)) ( https://en.wikipedia.org/wiki/Prime_number_theorem#Approximations_for_the_nth_prime_number )

Penjelasan

Tidak mudah membedakan aliran program dari perintah vim, jadi saya menulis ulang dengan Python mengikuti aliran yang sama. Seperti kode Vim, kode python akan error ketika mencapai akhir. Python tidak suka terlalu banyak rekursi; jika Anda mencoba kode ini dengan N> 150 atau lebih, itu akan mencapai kedalaman rekursi maksimum

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()

Sekarang, untuk memecah penekanan tombol yang sebenarnya!

  • qpqqdqMenghapus register @d dan @p. Ini akan memastikan tidak ada yang berjalan saat mengatur makro rekursif ini.

  • A^V^Ayyp<Esc>3h"aC@a<Esc>0C1<Esc>@"ddMengubah input menjadi daftar angka dari 2 menjadi N + 1. Entri N +1 dihapus sebagai efek samping dari pengaturan makro @d.

    • Secara khusus, tulis makro yang menambah angka, lalu salin di baris berikutnya, lalu tulis 1 dan jalankan makro N kali ini.
  • mpqdmd"bywo^Ra ^Rb 0 0 `pj@p ^Ra 0 ^R=@a%@b<Enter> `pdd@p 0 `dj@d<Esc>0*w*wyiWdd@0qmenulis makro @d, yang mengimplementasikan fungsi d () di atas. Pernyataan "Jika" menarik untuk diterapkan di Vim. Dengan menggunakan operator pencarian *, dimungkinkan untuk memilih jalur tertentu untuk diikuti. Memecah perintah lebih jauh kita dapatkan

    • mpqdTetapkan tanda p di sini dan mulai merekam @d makro. Tanda p perlu diatur sehingga ada titik yang diketahui untuk melompat saat ini berjalan
    • o^Ra ^Rb 0 0 `pj@p ^Ra 0 ^R=@a%@b<Enter> `pdd@p 0 `dj@d<Esc> Menulis teks pernyataan if / else
    • 0*w*wyiWdd@0 sebenarnya mengeksekusi pernyataan if.
    • Sebelum menjalankan perintah ini, baris tersebut akan berisi @a @b 0 0 `pj@p @a 0 (@a%@b) `pdd@p 0 `dj@d
    • 0 memindahkan kursor ke awal baris
    • *w*w Memindahkan kursor ke kode yang akan dieksekusi berikutnya

      1. Jika @a == @b, yaitu `pj@p, yang bergerak ke nomor berikutnya untuk @a dan menjalankan @p di atasnya.
      2. jika @a! = @b dan @ a% @ b == 0, yaitu `pdd@p, yang menghapus angka saat ini @a, kemudian jalankan @p pada yang berikutnya.
      3. jika @a! = @b dan @ a %% b! = 0, yaitu `dj@d, yang memeriksa angka berikutnya untuk @b untuk melihat apakah itu adalah faktor @a
    • yiWdd@0 menarik perintah ke register 0, menghapus baris dan menjalankan perintah

    • q mengakhiri rekaman makro @d
  • Saat ini pertama kali dijalankan, `pdd@pperintah dijalankan, menghapus baris N +1.

  • qpmp"aywgg@dq menulis @p makro, yang menyimpan nomor di bawah kursor, kemudian pergi ke entri pertama dan menjalankan @d pada itu.

  • gg@p sebenarnya mengeksekusi @p sehingga akan mengulangi seluruh file.


3

QBASIC, 98 Chars, Complexity N Sqrt (N), Score 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:

Saya telah sedikit memodifikasi pernyataan masalah, yang sekarang menemukan bilangan prima 'n' pertama, saya minta maaf karena tidak ada pemberitahuan
Optimus

Saya kira kita dapat mengasumsikan input "sumber" untuk program ini; yaitu, input adalah angka tepat setelah IF K=(jadi panjang program tidak termasuk angka). Seperti berdiri, program ini mencetak n primes pertama tidak termasuk 2, yang dapat diperbaiki dengan menambahkan ?2di awal, dan mengubah K=...ke K=...-1. Program ini juga dapat golfed sedikit dengan mengambil ruang dari J=2 TO, J=0 THEN, K=...-1 THEN, dan dengan menghapus Indentasi tersebut. Saya percaya ini menghasilkan program 96 karakter.
res

3

Scala 263 karakter

Diperbarui agar sesuai dengan persyaratan baru. 25% dari kesepakatan kode dengan menemukan batas atas yang wajar untuk menghitung bilangan prima di bawah ini.

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"))
}

Saya juga mendapat ayakan.

Berikut ini adalah uji empiris dari biaya perhitungan, yang tidak dianalisa untuk analisis:

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 

mengarah ke penghitungan berikut:

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

Saya tidak yakin bagaimana cara menghitung skor. Apakah layak untuk menulis 5 karakter lagi?

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)

Untuk yang lebih besar dan mengurangi perhitungan sekitar 16% dalam kisaran itu, tetapi afaik untuk rumus skor, kita tidak mempertimbangkan faktor konstan?

Pertimbangan Big-O baru:

Untuk menemukan 1 000, 10 000, 100 000 bilangan prima dan seterusnya, saya menggunakan rumus tentang kepadatan bilangan prima x => (math.log (x) * x * 1.3 yang menentukan lingkaran luar yang saya jalankan.

Jadi untuk nilai i dalam 1 hingga 6 => NPrimes (10 ^ i) berjalan 9399, 133768 ... dikali loop luar.

Saya menemukan fungsi-O ini berulang dengan bantuan dari komentar Peter Taylor, yang menyarankan nilai eksponensial yang jauh lebih tinggi, daripada 1,01 ia menyarankan 1,5:

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

O: (n: Int) Panjang

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

ns: Daftar [Panjang] = Daftar (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

Ini adalah quotients, jika saya menggunakan 1.01 sebagai eksponen. Inilah yang konter temukan secara empiris:

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

Dua nilai pertama adalah outlier, karena saya telah membuat koreksi konstan untuk formulasi estimasi saya untuk nilai-nilai kecil (hingga 1000).

Dengan saran Peter Taylors 1,5, akan terlihat seperti:

245.2396265560166
98.8566987153728
70.8831374743478
59.26104390040363
52.92941829568069
48.956394784317816

Sekarang dengan nilai saya, saya dapat:

O(263)
res85: Long = 1576

Tapi saya tidak yakin, seberapa dekat saya dengan fungsi-O saya dengan nilai-nilai yang diamati.


Maaf saya membuat beberapa perubahan pada pernyataan masalah untuk mengurangi beberapa ambiguitas terkait dengan kompleksitas, (Saya yakin solusi Anda tidak akan banyak berubah)
Optimus

Ini adalah pembagian percobaan yang efektif oleh bilangan prima. Jumlah kali melalui loop dalam adalah O(M^1.5 / ln M), dan setiap kali melalui Anda melakukan O(ln M)pekerjaan (tambahan), jadi secara keseluruhan itu O(M^1.5) = O((n ln n)^1.5).
Peter Taylor

Dengan ^ 1.02 bukannya ^ 1.5 def O(n:Int) = (math.pow((n * math.log (n)), 1.02)).toLongsaya lebih dekat ke nilai-nilai, secara empiris ditemukan dengan penghitung saya. Saya memasukkan temuan saya di posting saya.
pengguna tidak diketahui

3

Ruby 66 chars, O (n ^ 2) Skor - 4356

lazytersedia sejak Ruby 2.0, dan 1.0/0merupakan trik keren untuk mendapatkan rentang tak terbatas:

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

1
Anda dapat mencukur satu char off dengan mengubahnya ke(2..(1.0/0)).lazy.select{|i|!(2...i).any?{|j|i%j<1}}.take(n).to_a
Qqwy

Atau bahkan: (Ini membuat solusi kurang efisien, tetapi tidak mengubah batas atas O (n²)) (2..(1.0/0)).lazy.select{|i|(2..i).one?{|j|i%j<1}}.take(n).to_a. Ini memangkas dua karakter lagi.
Qqwy

Mengubahnya dengan baik (2..(1.0/0)).lazy.select{|i|!(2...i).any?{|j|i%j<1}}.first(n)akan menghasilkan 61 karakter.
Richie

2

Ruby, 84 karakter, 84 byte, skor?

Yang ini mungkin agak terlalu pemula untuk bagian ini, tetapi saya bersenang-senang melakukannya. Itu hanya loop sampai f(bilangan prima ditemukan) sama dengan n, jumlah bilangan prima yang diinginkan dapat ditemukan.

Bagian yang menyenangkan adalah bahwa untuk setiap loop itu menciptakan sebuah array dari 2 menjadi satu kurang dari jumlah yang diperiksa. Kemudian memetakan setiap elemen dalam array menjadi modulus dari angka asli dan elemen, dan memeriksa untuk melihat apakah ada hasilnya nol.

Juga, saya tidak tahu bagaimana mencetaknya.

Memperbarui

Kode dipadatkan dan menyertakan nilai (benar-benar arbitrer) untuk 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

Asli

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

The i += 1bit dan untillingkaran adalah semacam melompat keluar pada saya sebagai area untuk perbaikan, tapi di trek ini aku semacam terjebak. Bagaimanapun, itu menyenangkan untuk dipikirkan.


2

Scala, 124 karakter

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}

Divisi uji coba sederhana hingga akar kuadrat. Kompleksitas karena itu harus O (n ^ (1,5 + epsilon))

124 ^ 1,5 <1381, jadi itu nilai saya, saya kira?


1

Perl - 94 karakter, O (n log (n)) - Nilai: 427

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

Python - 113 karakter

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 byte

Terjemahan: Lihat Bu! Hanya menambah dan beberapa pembukuan!

File 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}}

Menjalankan:

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

BASH, 133 byte

File 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

Menjalankan:

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

Bilangan prima dihitung dengan membiarkan bilangan prima yang sudah ditemukan melompat pada "pita bilangan bulat positif". Pada dasarnya ini adalah Saringan Of Eratosthenes.

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

... adalah algoritma yang sama dalam Python dan mencetak waktu ketika l -th prime ditemukan alih-alih prime itu sendiri.

Output diplot dengan gnuplothasil sebagai berikut:

masukkan deskripsi gambar di sini

Lompatan mungkin ada hubungannya dengan keterlambatan file i / o karena menulis data buffer ke disk ...

Dengan menggunakan jumlah bilangan prima yang jauh lebih besar untuk menemukan, akan membawa penundaan tambahan yang bergantung pada sistem ke dalam gim, misalnya larik yang mewakili "pita bilangan bulat positif" tumbuh terus-menerus dan cepat atau lambat akan membuat setiap komputer meminta lebih banyak RAM (atau kemudian ditukar).

... jadi mendapatkan gagasan tentang kompleksitas dengan melihat data eksperimental tidak banyak membantu ... :-(


Sekarang menghitung penambahan yang dibutuhkan untuk menemukan nbilangan prima:

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

masukkan deskripsi gambar di sini


Bagaimana Anda membuat grafik itu?
kucing

1
Gnuplotdengan set term xtermdan kemudian tangkapan layar xtermjendela grafis (mungkin fitur yang hampir dilupakan). ;-)

0

Scala 121 (99 tanpa boilerplate kelas Utama)

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 byte

Solusi ini sedikit sepele, karena menghasilkan 0 di mana bilangan tidak prima, tetapi saya tetap akan mempostingnya:

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)

Juga, saya tidak yakin bagaimana menghitung kompleksitas suatu algoritma. Tolong jangan mundur karena ini. Sebaliknya, bersikap baik dan berkomentar bagaimana saya bisa menyelesaikannya. Juga, beri tahu saya bagaimana saya bisa mempersingkat ini.


Saya pikir Anda dapat menempatkan print(i)pada baris yang sama seperti untuk loop dan menghapus spasi di in [2], 0 if, 0 in [i%jdan +1,2)] else.
acrolith

@daHugLenny Wow, terima kasih banyak! Saya akan mengedit posting saya sebentar lagi. :-D
0WJYxW9FMN

@daHugLenny Apakah Anda tahu cara menghitung efisiensi secara kebetulan?
0WJYxW9FMN

Tidak, maaf (Komentar harus setidaknya 15 karakter)
acrolith

Bagaimanapun, terima kasih. Anda membuat program saya yang paling singkat di sini!
0WJYxW9FMN


0

Perl 6, 152 byte, O (n log n log (n log n) log (log (n log n))) (?), 9594,79 poin

Menurut halaman ini , kompleksitas bit untuk menemukan semua bilangan prima hingga n adalah O (n log n log log n); kompleksitas di atas menggunakan fakta bahwa nth prime sebanding dengan 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]

tidak memenuhi syarat, lakukan di Wentel untuk memenuhi syarat
noɥʇʎԀʎzɐɹƆ

Maaf, tapi apa maksudmu?
bb94

untuk hadiah (fiiiiiiiiilerrrrr)
noɥʇʎԀʎzɐɹƆ

0

Groovy (50 Bytes) - O (n * sqrt (n)) - Skor 353.553390593

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

Dimasukkan dalam n dan menampilkan semua angka dari 1 hingga n yang prima.

Algoritma yang saya pilih hanya keluaran primes n> 2, jadi menambahkan 1,2 di awal diperlukan.

Kerusakan

x%it - Kejujuran tersirat jika tidak dapat dibagi, salah jika itu benar.

(2..x**0.5).every{...}- Untuk semua nilai antara 2 dan sqrt (x) memastikan bahwa mereka tidak dapat dibagi, untuk ini mengembalikan true, harus mengembalikan true untuk setiap .

(1..it).findAll{x->...} - Untuk semua nilai antara 1 dan n, temukan semua yang sesuai dengan kriteria tidak dapat dibagi antara 2 dan sqrt (n).

{[1,2]+...}​ - Tambahkan 1 dan 2, karena mereka selalu prima dan tidak pernah dicakup oleh algoritma.


0

Racket 155 byte

(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))]))

Itu membuat daftar bilangan prima yang ditemukan dan memeriksa pembagian masing-masing nomor berikutnya dengan bilangan prima yang sudah ditemukan. Selain itu, ia memeriksa hanya sampai akar kuadrat dari angka yang diuji karena itu sudah cukup.

Tidak Disatukan:

(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
    )))

Pengujian:

(nprimes 35)

Keluaran:

'(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 (kompleksitas N ^ 2)

lain awk, untuk primes hingga 100 digunakan seperti ini

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

kode golf bagian yang dihitung adalah

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

yang dapat dimasukkan ke dalam file skrip dan dijalankan sebagai awk -f prime.awk <(seq 100)


0

Javascript, 61 karakter

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

Sedikit lebih buruk dari O (n ^ 2), akan kehabisan ruang stack untuk n besar.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.