En verimli ve en kısa koddaki ilk n-asal sayıların listesi [kapalı]


27

Kurallar basit:

  • İlk n primiler ( n'nin altındaki değil ), yeni satırlarla ayrılmış standart çıktılara basılmalıdır (primiler kod içinde oluşturulmalıdır)
  • primerler dahili bir işlev veya bir kütüphane aracılığıyla üretilemez , yani prime = get_nth_prime (n), is_a_prime (number) veya factorlist = list_all_factors (number) gibi dahili veya kütüphane işlevlerinin kullanımı çok yaratıcı olmaz.
  • Puanlama - Diyelim ki, Puan = f ([koddaki karakter sayısı]), O ( f (n)) algoritmasını, n'in bulduğu primerlerin sayısı olduğu gibi tanımlıyoruz. Örneğin, O (n ^ 2) karmaşıklığına sahip 300 karakter kodunuz varsa , puan 300 ^ 2 = 90000 , O (n * ln (n)) olan 300 karakter için puan 300 * 5.7 = 1711.13 ( tüm günlüklerin basitlik için doğal günlükler olduğunu varsayalım)

  • Mevcut herhangi bir programlama dilini kullanın, en düşük puan kazanır

Düzenleme: Sorun, çünkü O (f (n)) ne 'n' ile ilgili kafa karışıklığı 'ilk n asal' olarak bulgu gelen ilk 1000000 asal 'olarak değiştirildi olduğunu n bulduğunuz asal sayısı (asal bulma olduğunu Buradaki problem ve bu yüzden problemin karmaşıklığı bulunan prime sayısına bağlıdır.

Not: Karmaşıklık konusundaki bazı kafa karışıklıklarını netleştirmek için, eğer 'n' bulduğunuz primerlerin sayısı ve 'N' bulunan ilk üs ise, n'nin karmaşıklığı n'dir ve N eşdeğer değildir, yani O (f (n))! = O (f (N)) olarak, f (N)! = Sabit * f (n) ve N! = Sabit * n, çünkü en yüksek fonksiyonun doğrusal olmadığını biliyoruz, çünkü 'n' bulduğumuzdan beri Asal karmaşıklık, 'n' cinsinden kolayca anlaşılabilir olmalıdır.

Kibbee işaret ettiği gibi, ziyaret edebilirsiniz Bu siteyi çözümlerinizi doğrulamak için ( burada , eski google dokümanlar listesi)

Lütfen bunları çözümünüze ekleyin -

  • Programınızın ne kadar karmaşıklığı varsa (önemsiz değilse temel analizi de ekleyin)

  • kodun karakter uzunluğu

  • final hesaplanan puan

Bu benim ilk CodeGolf Sorum, bu yüzden yukarıdaki kurallarda bir hata veya boşluk varsa lütfen belirtin.



2
Buna cevabım 1[\p:i.78498bunun cevabıydı 1[\p:i.1000000. J'nin içsel asal algoritmasının O (n ^ 2) olduğunu
Gareth

2
Kimse karmaşıklığını düzgün bir şekilde hesaplamayı başaramadı. Konusunda karışıklık var nasal veya maksimum asal sayısı ve aralıktaki sayıların eklenmesi herkesin gerçeği göz ardı 0..nolduğunu O(logn)ve çarpma ve bölme daha pahalıdır. Doğru karmaşıklıkları ile birlikte bazı örnek algoritmalar vermenizi öneririm.
ugoren

3
Bir k-bit sayısı için mevcut en iyi bilinen birincillik testi O-tilde(k^6). Bu, çalışma süresi daha iyi olduğunu iddia eden herkesin O-tilde(n ln n (ln(n ln n))^6)sorunun bir bölümünü yanlış anladığını ima ediyor ; ve O-tildepuanlamada karmaşıklıkların nasıl ele alınması gerektiği sorusu .
Peter Taylor

2
Hiç kimse, O (n) 'nin karmaşıklık açısından O (kn)' ye (k sabit için) eşit olduğunu, ancak puan açısından olmadığını belirtmemiştir. Örneğin, karmaşıklığımın O (n ^ 10) olduğunu varsayalım. Bu, O (n ^ 10 * 1E-308) 'e eşittir ve hala korkunç karmaşıklığı olan büyük bir programla mücadeleyi kazanabilirim.
JDL

Yanıtlar:


10

Python (129 karakter, O (n * log log n), 203.948 puanı)

Eratosthenes Elek gitmek için yol olduğunu söyleyebilirim. Çok basit ve nispeten hızlı.

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

Önceden geliştirilmiş kod.

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

Karmaşıklığı hiç hesaplayamıyorum, verebileceğim en iyi yaklaşım budur.

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)))olan üst sınır arasında ninci asal sayı.


1
Karmaşıklık (ve dolayısıyla puanlama) hesaplaması üst sınıra dayanır, nancak asal sayılara dayanmaz. Dolayısıyla, puanın daha yüksek olması gerektiğini düşünüyorum. Yukarıdaki yorumuma bakın.
Howard

Üst sınır n? Bu da ne?
beary605

Burada üst sınır N=15485864. Temel karmaşıklık hesaplamaları için (primerlerin yoğunluğu nedeniyle) n=1000000söyleyebilirsiniz N=n*log(n).
ugoren

Eğer puanımın sabitlenmesi gerekiyorsa, lütfen benim için düzeltin, hala puanlama sistemini iyi anlamadım.
beary605,

@ beary605 ilk n harfi bulmak için problemleri değiştirirsem olur mu? Bu karmaşıklık ve n'nin O (f (n)) 'da ne olduğu konusunda bir kafa karışıklığı çözecektir
Optimus

7

Haskell, n ^ 1.1 ampirik büyüme hızı, 89 karakter, skor 139 (?)

Aşağıdakiler, kullandığı genel kitaplığın daha önce yüklendiği zaman GHCi'de çalışır. Baskı n -inci asal, 1 tabanlı:

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

Bu, sıralı listeler için genel kullanımlı bir kütüphane kullanan, sınırlandırılmamış Eratosthenes elektir. 100.000 ila 200.000 prim arasındaki ampirik karmaşıklık O(n^1.1). İçin uygun O(n*log(n)*log(log n)).

Karmaşıklık tahmini hakkında

100k ve 200k primerler için çalışma zamanını ölçtüm, sonra logBase 2 (t2/t1)üretilen hesaplandı n^1.09. Tanımlama g n = n*log n*log(log n), hesaplama imkanı logBase 2 (g 200000 / g 100000)verir n^1.12.

O zaman, 89**1.1 = 139yine de g(89) = 600. --- (?)

Puanlamada, karmaşıklık fonksiyonunun yerine tahmini büyüme oranının kullanılması gerektiği görülmektedir. Örneğin g2 n = n*((log n)**2)*log(log n), çok daha iyidir n**1.5, ancak 100 karakter için ikisi sırasıyla 3239ve puanlarını 1000verir. Bu doğru olamaz. 200k / 100k aralığında tahmin yapmak logBase 2 (g2 200000 / g2 100000) = 1.2ve böylece puan verir 100**1.2 = 251.

Ayrıca, Tüm asal çıktısını girişiminde, sadece yok n -inci asal yerine.

İthalat yok, 240 karakter. n ^ 1.15 ampirik büyüme hızı, puan 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

Karakter sayısı başına en yüksek puan kazanır mı? İlk N için değiştirildi. Ayrıca hesap makinesini kullanamıyorum, bu yüzden puanım düşündüğüm kadar kötü değil. (aşağıdaki kaynakta bulunan temel deneme bölümü için karmaşıklığı kullanmak).

Gereğince Will Ness aşağıda tam Haskell programı değildir (aslında repl dayanır). Aşağıdaki bir sözde elek ile daha eksiksiz bir programdır (ithalat aslında bir char kurtarır, ancak kod golf ithalatı sevmiyorum).

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

Bu sürüm şüphesiz (n ^ 2). Algoritma, saf "` elek "nin sadece golf versiyonudur, burada görüldüğü gibi Old ghci 1 liner

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

Eski, hile yapan cevabı bırakmak, bağladığı kütüphanesi oldukça hoş.

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

Bir uygulama ve zaman karmaşıklığının bağlantıları için buraya bakınız . Maalesef tekerleklerin kayıt süresi (n) arama süresine sahip ve bizi bir faktör yavaşlatıyor.


• asallar yerleşik bir
functon

@ walpen Üzgünüm kuralları bildirimde bulunmadan değiştirdim, lütfen uygun gördüğünüz değişiklikleri yapın
Optimus

Karmaşıklık, O ((n ln n) ^ 1.5 ln (n ln n) ^ 0.585) gibi bir şey olmaz mıydı? (Veya O ((n ln n) ^ 1.5 ln (n ln n)) Haskell, sandığım gibi, Karatsuba yerine saf bir bölüm kullanıyorsa)
Peter Taylor

Hayır, çünkü bu bana korkunç bir puan veriyor:. Ama eminim haklısın. Sadece deneme bölünmesine benziyordu ve bu da deneme bölünmesinin zaman karmaşıklığıydı (belki de, muhtemelen yanlış bir kaynağı okuduğuma göre), bunu seçtim. Şimdilik puanımı NaN diyeceğim, bu güvenli görünüyor.
walpen,

Sanırım (Haskell'im ihmal edilebilir, ancak SML'de yapmanın nasıl doğal olacağını biliyorum ...) sadece daha küçük primerler ile deneme bölümü yapıyorsunuz, bu durumda bir P'deki deneme bölümü O ( P ^ 0.5 / ln P) bölümleri. Fakat P'nin k biti varsa, bir bölünme O (k ^ 1.585) (Karatsuba) veya O (k ^ 2) (naïve) zaman alır ve O (n lg n) O (ln n lg n)) bit.
Peter Taylor,

5

C #, 447 Karakterler, Bayt 452, Puan?

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

scriptler Variant, 381 Karakterler, 385 Bayt, Skor?

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

Eğer komut dosyalarını yüklerseniz, onu çalıştırabilirsiniz.

PS Bunu Vim'de yazdım. :D


2
Gereksiz beyaz boşlukları kaldırarak bazı karakterleri kaydedebilirsiniz. Örneğin, bir =ve <işareti etrafına boşluk koymak gerekmez . Ayrıca, bu kod için bayt ve karakterlerde bir fark olduğunu sanmıyorum - bu 548 karakter ve 548 bayttır.
ProgramFOX

2
Oh teşekkürler, bu benim ilk CodeGolf'um!
XiKuuKy,

4

GolfScript (45 karakter, puan talep edildi ~ 7708)

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

Bu, basit deneme bölümlerini asal sayılarla yapar. Ruby'nin kesme kenarının yakınındaysa (yani 1.9.3.0 kullanarak) aritmetik Toom-Cook 3 çarpımını kullanıyorsa, bir deneme bölümü O (n ^ 1.465) olur ve bölümlerin toplam maliyeti O((n ln n)^1.5 ln (n ln n)^0.465) = O(n^1.5 (ln n)^1.965)† olur. Ancak, GolfScript'te bir diziye bir öğe eklemek dizinin kopyalanmasını gerektirir. Bunu, astar listesini yalnızca yeni bir astar bulduğunda, yalnızca ntoplam olarak kopyalamak için optimize ettim . Her kopyalama işlemi, † O(n)boyutunda olan öğelerdir .O(ln(n ln n)) = O(ln n)O(n^2 ln n)

Ve bu, erkekler ve kızlar, GolfScript'in ciddi programlama yerine golf oynamak için kullanılmasının nedeni budur.

O(ln (n ln n)) = O(ln n + ln ln n) = O(ln n). Çeşitli yazılar hakkında yorum yapmadan önce bunu fark etmeliydim ...


4

Bu çok kolaydır, metin editörüm bile bunu yapabilir!

Vim: 143 tuş vuruşları (115 işlem): O (n ^ 2 * log (n)): Puan: 101485.21

Gönderme:

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

Giriş: N boş bir belgenin ilk satırında olmalıdır. Bu bittikten sonra, 2'den N'ye her asal ayrı bir çizgi olacaktır.

Komutları Çalıştırmak:

Öncelikle, önünde bir şapka olan herhangi bir komutun Ctrl tuşunu basılı tutmanız ve bir sonraki harfi yazmanız gerektiği anlamına geldiğini unutmayın (örn. ^ V Ctrl-vve ^ R Ctrl-r).

Bu @a, @b, @d ve @p kayıtlarınızdaki herhangi bir şeyin üzerine yazacaktır.

Bu qkomutları kullandığından , yalnızca bir makroya yerleştirilemez. Ancak, işte onu çalıştırmak için bazı ipuçları.

  • qpqqdq sadece kayıtları temizler
  • A^V^Ayyp<Esc>3h"aC@a<Esc>0C1<Esc>@"dd2 ile N + 1 arasında bir sayı listesi oluşturacaktır. Bu iki ana parça arasında bir kırılmadır, bu yüzden bir kez yapıldığında, tekrar yapmanız gerekmez
  • 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@ptek seferde yazılması gerekir. Bir şeyleri mahvedebileceği için geri adımdan kaçının.
    • Hata yaparsanız, qdqqpqbu satırı tekrar deneyin.

Büyük N için bu çok yavaş. N = 5000'in çalışması yaklaşık 27 dakika sürdü; Kendinizi uyarılmış olarak düşünün.

Algoritma:

Bu, primerleri bulmak için temel bir özyinelemeli algoritma kullanır. 1 ile A arasındaki tüm asalların bir listesi göz önüne alındığında, A + 1, asal listesindeki herhangi bir sayı tarafından bölünemezse asaldır. A = 2 ile başlayın ve bulundukları listeye primerler ekleyin. N özyinelemelerinden sonra, liste N'ye kadar olan tüm astarları içerecektir.

karmaşa

Bu algoritma, N'nin giriş numarası ve n'nin N'e kadar olan primerlerin sayısı olduğu, O (nN) 'nin karmaşıklığına sahiptir, her yineleme testi n sayıları ve N yinelemeleri O (nN) vererek gerçekleştirilir.

Ancak, N ~ n * log (n), son karmaşıklığı O (n 2 * log (n)) olarak verir ( https://en.wikipedia.org/wiki/Prime_number_theorem#Approximations_for_the_nth_prime_number )

açıklama

Program akışını vim komutlarından ayırt etmek kolay değil, bu yüzden aynı akışı izleyerek Python'da yeniden yazdım. Vim kodu gibi, python kodu da sonuna geldiğinde hata verir. Python çok fazla özyinelemeden hoşlanmaz; Bu kodu N> 150 ya da öylesine denerseniz, maksimum yineleme derinliğine ulaşacaktır

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

Şimdi, gerçek tuş vuruşlarını kırmak için!

  • qpqqdq@D ve @p kayıtlarını temizler. Bu, özyinelemeli makroları ayarlarken hiçbir şeyin çalışmamasını sağlar.

  • A^V^Ayyp<Esc>3h"aC@a<Esc>0C1<Esc>@"ddGirişi 2 - N + 1 arasında bir sayı listesine dönüştürür. N + 1 girişi, @d makrosunu kurmanın yan etkisi olarak silinir.

    • Spesifik olarak, bir sayıyı arttıran bir makro yazar, ardından bir sonraki satıra kopyalar, sonra bir 1 yazar ve bu makroyu N defa yürütür.
  • mpqdmd"bywo^Ra ^Rb 0 0 `pj@p ^Ra 0 ^R=@a%@b<Enter> `pdd@p 0 `dj@d<Esc>0*w*wyiWdd@0qYukarıdaki d () işlevini uygulayan @d makrosunu yazar. "If" ifadelerinin Vim'de uygulanması ilginçtir. Arama operatörünü * kullanarak, izlenecek belirli bir yolu seçmek mümkündür. Emri daha da bozmak

    • mpqdBurada p işaretini ayarlayın ve @d makrosunu kaydetmeye başlayın. P işaretinin ayarlanması gerekir, böylece bu ilerledikçe atlanacak bilinen bir nokta vardır.
    • o^Ra ^Rb 0 0 `pj@p ^Ra 0 ^R=@a%@b<Enter> `pdd@p 0 `dj@d<Esc> İf / else ifadesi metnini yazar
    • 0*w*wyiWdd@0 aslında if ifadesini çalıştırır.
    • Bu komutu çalıştırmadan önce, satır içerecektir @a @b 0 0 `pj@p @a 0 (@a%@b) `pdd@p 0 `dj@d
    • 0 imleci satırın başına getirir
    • *w*w İmleci bir sonraki çalıştırılacak koda götürür

      1. if @a == @b, yani, @a `pj@piçin bir sonraki sayıya gider ve üzerinde @ çalışır.
      2. @a! = @b ve @ a% @ b == 0 ise `pdd@p, bu @a geçerli sayıyı siler, sonra bir sonraki sayfada p çalışır.
      3. if @a! = @b ve @% a% b! = 0 ise `dj@d, bir sonraki sayıyı @a faktörü olup olmadığını görmek için kontrol eder.
    • yiWdd@0 komutu 0 registerına yönlendirir, satırı siler ve komutu çalıştırır

    • q @d makrosunun kaydını bitirir
  • Bu ilk çalıştırıldığında, `pdd@pN + 1 satırını silerek komut çalıştırılır.

  • qpmp"aywgg@dq İmlecin altındaki sayıyı kaydeden @p makrosunu yazar, sonra ilk girişe gider ve üzerinde @d komutunu kullanır.

  • gg@p aslında, p'nin tamamını çalıştırır, böylece tüm dosya üzerinde yinelenir.


3

QBASIC, 98 Karakter, Karmaşıklık N Sqrt (N), Puan 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:

Sorun bildirimini biraz değiştirdim, şimdi ilk 'n' primesini buldum, bildirimde bulunmadığım için üzgünüm
Optimus

Sanırım bu program için "kaynak" girişini varsayabiliriz; yani giriş, hemen sonraki sayıdır IF K=(bu nedenle programın uzunluğu rakamı içermez). Haliyle, programın ilave edilmesi suretiyle tespit edilebilmektedir 2 dahil değil ilk n asal, yazdırır ?2başında ve değişen K=...için K=...-1. Bu program aynı zamanda üzerinden boşluk alarak biraz golfed olabilir J=2 TO, J=0 THEN, K=...-1 THENve girintilemeyi kaldırarak. Bunun 96 karakterlik bir programla sonuçlandığına inanıyorum.
res

3

Scala 263 karakter

Yeni gereksinimlere uyacak şekilde güncellendi. Kodun% 25'i, aşağıdaki primerleri hesaplamak için makul bir üst sınır bulma ile ilgilidir.

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

Benim de bir elek var.

Analiz için temel alınan hesaplama maliyetlerinin ampirik bir testi:

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 

aşağıdaki sayıları yol açar:

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

Skoru nasıl hesaplayacağımı bilmiyorum. 5 karakter daha yazmaya değer mi?

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)

Daha büyük n için hesaplamaları bu aralıkta yaklaşık% 16 oranında azaltır, ancak skor formülü için afaik olarak, sürekli faktörleri dikkate almayız mı?

Yeni Big-O değerlendirmeleri:

1 000, 10 000, 100 000 asal vb. Bulmak için, çalıştırdığım dış döngüyü belirleyen x => (math.log (x) * x * 1.3) primerlerinin yoğunluğu hakkında bir formül kullanıyorum.

Yani, 1'den 6'ya kadar olan değerler için => NPrimes (10 ^ i) dış döngüden 9399, 133768 ... çarpı çalışır.

Bu O-fonksiyonunu yinelemeyle üstel için üstelik çok daha yüksek bir değer öneren Peter Taylor'ın yorumuyla, 1.01 yerine 1.5 buldum:

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

O: (n: Int) Uzun

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

ns: Liste [Uzun] = Liste (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

Eğer üs olarak 1.01 kullanırsam bu bölümler. Tezgahın ampirik olarak bulduğu şey:

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

İlk iki değer aykırı değerlerdir, çünkü küçük değerler için tahmin formülü için sürekli bir düzeltme yaptım (1000'e kadar).

Peter Taylors'in 1.5 önerisi ile şöyle olurdu:

245.2396265560166
98.8566987153728
70.8831374743478
59.26104390040363
52.92941829568069
48.956394784317816

Şimdi değerimle alıyorum:

O(263)
res85: Long = 1576

Fakat emin değilim, O-fonksiyonumla gözlemlenen değerlere ne kadar yakın gelebilirim.


Üzgünüm, karmaşıklıkla ilgili bazı belirsizlikleri azaltmak için problem açıklamasında bazı değişiklikler yaptım, (çözümünüzün çok fazla değişmeyeceğinden eminim)
Optimus

Bu, prime göre deneme bölümüdür. İç döngüden kaç kez geçtiğiniz ve O(M^1.5 / ln M)sizden geçen her seferde O(ln M)iş (ekleme), yani genel olarak O(M^1.5) = O((n ln n)^1.5).
Peter Taylor,

^ 1.5 yerine ^ 1.02 ile def O(n:Int) = (math.pow((n * math.log (n)), 1.02)).toLongampirik olarak sayacımda bulunan değerlere daha çok yaklaşıyorum. Bulgularımı yazıma ekliyorum.
kullanıcı bilinmeyen

3

Ruby 66 karakter, O (n ^ 2) Puanı - 4356

lazyRuby 2.0'dan beri mevcut ve 1.0/0sonsuz bir menzile sahip olmak için harika bir numara:

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

1
Bir (2..(1.0/0)).lazy.select{|i|!(2...i).any?{|j|i%j<1}}.take(n).to_a
char'ı

Ya da: (Bu, çözümü daha az verimli yapar, ancak üst O (n²) sınırını değiştirmez) (2..(1.0/0)).lazy.select{|i|(2..i).one?{|j|i%j<1}}.take(n).to_a. Bu iki karakter daha tıraş.
Qqwy

Peki bunu değiştirmek (2..(1.0/0)).lazy.select{|i|!(2...i).any?{|j|i%j<1}}.first(n)61 karakterle sonuçlanacak.
Richie

2

Ruby, 84 karakter, 84 bayt, skor?

Bu, muhtemelen bu parçalar için biraz acemi, ama eğlenceli bir zaman geçirdim. Basitçe f(bulunan primiler) eşit n, bulunacak istenen primere eşit olana kadar döngüler .

İşin eğlenceli yanı, her döngü için incelenen sayıdan 2 ile 1 arasında bir dizi oluşturmasıdır. Daha sonra dizideki her elemanı orijinal sayının modülü ve eleman olarak eşler ve sonuçlardan herhangi birinin sıfır olup olmadığını kontrol eder.

Ayrıca nasıl skor alacağımı da bilmiyorum.

Güncelleştirme

Kod, sıkıştırılmış ve (tamamen rasgele) bir değer içeriyordu. 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

orijinal

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 += 1Bit ve untildöngü sıralama iyileştirme alanları olarak üzerime atlama, ama bu yolda ben tür sıkışmış ait değilim. Neyse, düşünmek eğlenceliydi.


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}

Kare kök kadar basit deneme bölümü. Karmaşıklık bu nedenle O (n ^ (1.5 + epsilon)) olmalıdır

124 ^ 1.5 <1381, sanırım puanım bu olurdu?


1

Perl - 94 karakter, O (n log (n)) - Puan: 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 bayt

Altyazı: Bak Anne! Sadece ekleme ve bazı defter tutma!

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

Koşmak:

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

BASH, 133 bayt

Dosya 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

Koşmak:

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

Asal sayılar, halihazırda bulunan primerleri "pozitif tamsayılar kaseti" üzerine atlatarak hesaplanır. Temelde seri hale getirilmiş Eratosthenes Elek.

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'da aynı algoritmadır ve lasalın kendisi yerine asalın bulunduğu zamanı gösterir.

Çizilen çıktı gnuplotaşağıdakileri verir:

görüntü tanımını buraya girin

Atlamalar muhtemelen diske arabelleğe alınmış veri yazması nedeniyle dosya g / Ç gecikmeleri ile ilgisi var ...

Bulmak için çok daha fazla primer sayısı kullanmak oyuna ek sisteme bağlı gecikmeler getirecektir, örneğin "pozitif tamsayılar kasetini" temsil eden dizi sürekli büyür ve er ya da geç her bilgisayarın daha fazla RAM (veya daha sonra takas) için ağlamasını sağlar.

... bu yüzden deneysel verilere bakarak karmaşıklık hakkında bir fikir edinmek gerçekten pek yardımcı olmuyor ... :-(


Şimdi nasal sayıları bulmak için gereken ilaveleri sayı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

görüntü tanımını buraya girin


Bu grafikleri nasıl yaptın?
kedi,

1
Gnuplotile set term xtermve daha sonra ekran görüntüsü xterm(unutulmuş özelliğine muhtemelen yakınında) bireyin grafik penceresinin. ;-)

0

Scala 121 (Ana sınıf kazan olmadan 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 bayt

Bu çözüm, bir sayının asal olmadığı 0 çıktısı olduğundan biraz önemsizdir, ancak yine de göndereceğim:

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)

Ayrıca, bir algoritmanın karmaşıklığını nasıl çözeceğimi bilmiyorum. Lütfen bu nedenle oy kullanma. Bunun yerine, kibar olun ve nasıl çözebileceğimi yorumlayın. Ayrıca, bunu nasıl kısaltabileceğimi söyle.


Sana koyabilirsiniz düşünüyorum print(i)döngü aynı satırda ve en boşlukları kaldırın in [2], 0 if, 0 in [i%jve +1,2)] else.
Saat

@daHugLenny Vay, çok teşekkürler! Gönderimi bir saniye içinde düzenleyeceğim. :-D
0WJYxW9FMN

@daHugLenny Verimliliğin herhangi bir şekilde nasıl hesaplanacağını biliyor musunuz?
0WJYxW9FMN 12:16

Hayır özür dilerim. (Yorumlar en az 15 karakter uzunluğunda
olmalı

Yine de teşekkürler. Programımı burada en kısa program yaptınız!
0WJYxW9FMN 12:16


0

Perl 6, 152 bayt, O (n log n log (n log n) log (log (n log n))) (?), 9594.79 puan

Bu sayfaya göre , n'ye kadar tüm primerleri bulmanın bit karmaşıklığı O (n log n log log n); Yukarıdaki karmaşıklık, nt üssünün n log n ile orantılı olduğu gerçeğini kullanır.

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]

kalifiye değil, kalifikasyon yapmak için
Wentel'da yapın

Pardon, ama ne demek istiyorsun?
bb94

ödül için (fiiiiiiiiilerrrrr)
noɥʇʎԀʎzɐɹƆ

0

Groovy (50 Bayt) - O (n * sqrt (n)) - Puan 353.553390593

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

N değerini alır ve asal olan 1 ile n arasındaki tüm sayıları verir.

Seçtiğim algoritma sadece n> 2 primer çıktılar, bu yüzden başlangıçta 1,2 eklenmesi gerekiyor.

Yıkmak

x%it - Bölünemez değilse, örtük hakikat, öyleyse sahtedir.

(2..x**0.5).every{...}- 2 ve sqrt (x) arasındaki tüm değerler bölünebilir olmadıklarından emin olun, bunun doğru olması için her birinin doğru olması gerekir .

(1..it).findAll{x->...} - 1 ile n arasındaki tüm değerler için, 2 ile sqrt (n) arasında bölünememe kriterlerine uygun olanları bulun.

{[1,2]+...}​ - 1 ve 2'yi ekleyin, çünkü her zaman birinci sınıftırlar ve asla algoritma kapsamazlar.


0

Raket 155 bayt

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

Bulunan asal sayıların bir listesini tutar ve her bir sonraki sayının bölünebilirliğini zaten bulunan asal sayılarla kontrol eder. Dahası, sadece test edilen sayıların kareköküne kadar kontrol eder, çünkü bu yeterlidir.

Ungolfed:

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

Test yapmak:

(nprimes 35)

Çıktı:

'(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 (karmaşıklık N ^ 2)

bir başkası awk, bunun gibi 100'e kadar kullanım için

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

kod golf parçası sayılır

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

bir komut dosyasına koyulabilir ve çalıştırılabilir 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)

O (n ^ 2) 'den biraz daha kötü, büyük n için yığın alanı tükenir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.