Doğal olarak oluşan bir primer jeneratör


42

Oldukça fazla sayıda prime üretme işlevi vardır. Hemen hemen hepsi inşa edilir ve Eratosthenes, Möbius fonksiyonu veya Wilson teoreminin eleklerine dayanır ve genellikle pratikte hesaplama yapmak mümkün değildir. Ancak, çok kolay bir yapıya sahip olan ve kazara bulunan jeneratörler de var.

2003 yılında Stephen Wolfram, NKS Yaz Okulu'ndaki canlı bir bilgisayar deneyinde bir iç içe yineleme denklemi sınıfını keşfetti. Matthew Frank'ın etrafındaki bir grup insan ek deneyler yaptı ve basitçe nüksetmenin ilginç bir özelliğini keşfetti

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

başlangıç ​​değeri ile a(1) = 7. Aradaki fark a(n) - a(n-1) = gcd(n,a(n-1))her zaman 1 ya da ana gibi görünüyordu. İlk birkaç fark: ( 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, ...

Eğer sadece 1'leri atlarsak aşağıdaki sırayı alırız ( 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 , birkaç yıl sonra bu listedeki her bir öğenin önceliğini kanıtladı. Görebildiğiniz gibi, primiler karıştırılır ve bazıları birden çok kez görünür. Aynı zamanda, dizinin sonsuz sayıda farklı primer içerdiği kanıtlanmıştır. Ayrıca, bütün garip primerlerin ortaya çıktığı varsayılmıştır.

Bu ana jeneratör inşa edilmediğinden, sadece kazayla bulunduğundan, ana jeneratöre "doğal olarak meydana gelen" adı verilir. Ancak pratikte bu jeneratörün de hesaplama yapmak için oldukça uygun olduğuna dikkat edin. Görünüşe göre, asal bir p sadece (p–3)/2ardışık 1s sonra görünür . Bununla birlikte, bu ana jeneratörü uygulamak sizin göreviniz olacaktır.

Meydan okuma:

nDizinin ilk öğelerini basan bir işlev veya program yazın A137613(1s dizisi olmayan). Giriş numarasını n >= 0STDIN, komut satırı argümanı, hızlı ya da işlev argümanı üzerinden okuyabilirsiniz . İlk nöğeleri herhangi bir okunabilir formatta STDOUT'a gönderin veya bu değerlere sahip bir dizi veya liste döndürün.

Bu kod golfü. Bu nedenle en kısa kod kazanır.

Liderler Sıralaması:

Burada hem düzenli bir lider tablosu hem de kazananların dile göre genel bir bakış oluşturması için bir Stack Snippet'i var. Cevabınızın göründüğünden emin olmak için, lütfen aşağıdaki Markdown şablonunu kullanarak cevabınızı bir başlık ile başlatın:

# Language Name, N bytes

N, gönderinizin büyüklüğüdür. Puanınızı yükseltirseniz, başlıkları üstüne vurarak eski skorları başlıkta tutabilirsiniz. Örneğin:

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


1
Asal jeneratör inşa edilmemiş olsa da, özyinelemeyi kullanarak bir deneme bölümü uygularsınız.
orlp

Eğer bir (1) = 7 ise, sıralama neden 7 ile başlamıyor?
feersum

3
@ feersum çünkü ilgilendiğimiz dizia(n)-a(n-1)
Maltysen

nSıfır olabilir
Sp3000

1
@jrenk Emin değilim. Belki 2 bayt olarak sayın (2 karakter çıkardığınızdan beri //) ve gönderiminizde açıklayın. Herhangi biri sizinle aynı fikirde değilse, yayınınızı her zaman düzenleyebilirsiniz.
Jakube

Yanıtlar:



7

Python 3.5.0b1 +, 95 93 bayt

Bağlantı Python 3.5.0b1 + salınımı

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

Aşağıdakileri içeren nüksün doğrudan bir uygulaması:

  • İyi dostumuz 1%xve
  • math.gcdaksine fractions.gcd.

Ne yapar 1%x? Yan soru: beta içeren Python'un revizyon geçmişinin belgelerini nerede bulabilirim? Düzenleme: Nevermind, revizyon tarihinin altında buldu .
mbomb007

@ mbomb007 yana x >= 1, 1%xiadeler 0 eğer x == 1, 1 aksi (eklemeye karar için kullanılan xlisteye)
SP3000

5

Julia, 110 bayt

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)

Ungolfed:

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

Vay, mükemmel bir 8k, güzel: D
Beta Decay

1
Yerine n<2kullanın n==1. Eğer geriye doğru yerine ileri bakarsak, ayrıca, kullanabilir i=1ve x=a(i)-a(i+=1)ve daha sonra println(-x)ve -x>1bu şekilde ayrı bir artış için ihtiyaç duymadan doğru için olumsuzluklara için i. Ve üç bayt, >=iki ise ... ama o zaman, ... n<1||()yerine kullanabilirsiniz, ama n>=1&&()yine de, ilk etapta bile gerekli değil (şartlı bırakma, n asla 1'den az olmayacak). Ayrıca bir (n) tanımlarken en dıştaki braketlere ihtiyacınız yoktur. Bu değişikliklerle, en azından 97 bayta ulaşmalısınız.
Glen O

5

PHP, 101 96 99 98 77 72 bayt

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


Kullanımı:
Senaryoyu bir argümanla arayın: php -d error_reporting=0 script.php 30
Eğer test etmek istiyorsanız ;extension=php_gmp.dllphp.ini'nizde uncomment yapmanız gerekir
-> extension=php_gmp.dll
Eklentiyi bayt sayıma eklemeli miyim? Düşüncesi olan var mı?


Günlük:
Ismael Miguel sayesinde 3 bayt kaydedildi.
Primo sayesinde 26 byte kurtarıldı.


1
Açılış etiketinizi kısaltıp <?tanımını kaldırabilirsiniz $j.
Ismael Miguel,

1
Evet, sayar. Ancak bu yeni çizgiyi kaldırabilirsiniz. Kod büyüklüğünüzü nasıl saydığınıza bağlı olarak, 1-2 bayt tasarruf edecek.
Ismael Miguel,

1
Küçük iyileştirmeler: Kullanım <içinde $j<=$argv[1](baskılar çok fazla bir) (-1). $eBaşlatılmamış bırakın , $e+7yerine kullanın (-3). Kullanım for(;;)yerine while()öncesi ve sonrası ifadeleri kullanılarak, (-2). echo$t.' ';$j++Ile değiştirin $j+=print"$t ", braketleri (-3) bırakın. (-2) if($t>1)ile değiştirin 2>$t||. Atama birleştirin $tkoşullu, anahtarlı ||için orparantez damla (-5). Hareket $argv[1]için $j, artışına tüm ifade hareket forkoşul (-2). Değişim >=$j+=printiçin -=print(3). Adım adım: codepad.org/s6LNSPSM
primo

1
@primo güzel açıklama için teşekkürler! Bunları yapabileceğimi bilmiyordum.
Jrenk

1
Birkaç tane daha: (-2) $e+7ile birleştirin $e+=$t. $iBaşlatılmamış bırakın , ~++$iyerine kullanın (-3). codepad.org/fDIImajp
primo

4

Haskell, 51 bayt

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

Not bu filk döner bir fonksiyonu olan N elemanları.

Aksine hesaplama daha a(n)sonra farklılıkları çalışma, biz farklılıkları hesaplamak d(n)ve almak için onları bir arada toplamak a(n). (Haskell ile aşina olmayanlar, a(n)ilk önce ihtiyacımız d(n)olanı protesto edebilirler , ama elbette tembel değerlendirme bizi bu soruna götürür!)

Ungolfed:

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 bayt

Çok kötü golf oynadı, önemli ölçüde azaltılabilir. Öndeki özyinelemeli işlevi tanımlar, .first-n'yi filtreler ve sonra farkı eşler.

L?tb+KytbibK7m-yhdyd.ft-yhZyZQ

Burada çevrimiçi deneyin .


Bu yanlış çıktı verirn = 0
Sp3000

2
@ Sp3000, Pyth'taki bir hatadır. Çekme talebinde bulunacağım.
Maltysen

Hata bulundu ve düzeltildi - yama DDoS'd olmayı kestikten sonra uygulanacak.
isaacg

1
İşte burada: meta.codegolf.stackexchange.com/questions/5318/… . Şahsen programlama dillerindeki hata düzeltmelerini bir cevap olarak değerlendiriyordum
Thomas Weller

2
@ThomasWeller Bu bütün dili başardı ...
isaacg

4

Julia, 69 67 bayt

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

Bu, soruna basit bir yinelemeli çözümdür. xAradaki fark budur gcdve sonra aekleyerek güncellerim x.



@alephalpha - Sanırım hatayı görüyorum. Kolayca sabitlenir. Bu süreçte bile iki bayt tıraş oldum.
Glen O

3

JavaScript (ES6), 91

Özyinelemeli gcd, yinelemeli ana fonksiyon. Çok hızlı değil.

Genel not: pasajı herhangi bir EcmaScript 6 uyumlu tarayıcıda çalıştırma testi (özellikle MSIE değil Chrome'da. Firefox’ta test ettim, Safari 9 gidebilirdi)

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 bayt

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

Buradaki numarayı kullandım: https://codegolf.stackexchange.com/a/39730/43318 ve puansız hale getirildi.

(Önceki: 71 bayt)

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

Önce a'nın sırasını yapın, sonra farklılıkları alın.

(Önceki: 74 bayt)

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

Standart liste fonksiyonları, ayrıca lambda fonksiyonunun akıllıca kullanımı. Not: Bu, 1 byte’dan daha belirgin olduğundan kısa

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

İthalatları saymazsak, bunu 66'ya indirebilirim.

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

3

PARI / GP, 60 bayt

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)) tanımından az ya da çok düz olarak alınmışsa

İçin çıktı 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 bayt

Thanks @Jakube - çıkışta 8 bayt kaydedildi.

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

Büyük olasılıkla birkaç bayt f, sonuçlarla bir dizi döndüren bir işlev tanımlayarak kaydedebilirsiniz . Bu şekilde dahil etmeyi, taramayı ve yazdırmayı kaldırabilirsiniz.
Jakube

2

Mathematica, 59 bayt

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