Ein natürlich vorkommender Primärgenerator

42

Es gibt eine große Anzahl von Funktionen zur Erzeugung von Primzahlen. Ziemlich alle von ihnen sind konstruiert und basieren auf dem Sieb von Eratosthenes, der Möbius-Funktion oder dem Wilson-Theorem und sind im Allgemeinen in der Praxis nicht berechenbar. Es gibt aber auch Generatoren, die einen sehr einfachen Aufbau haben und zufällig gefunden wurden.

Im Jahr 2003 untersuchte Stephen Wolfram eine Klasse verschachtelter Wiederholungsgleichungen in einem Live-Computerexperiment an der NKS Summer School. Eine Gruppe von Menschen um Matthew Frank hat daraufhin weitere Experimente durchgeführt und eine interessante Eigenschaft der einfachen Wiederholung entdeckt

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

mit dem Startwert von a(1) = 7. Der Unterschied a(n) - a(n-1) = gcd(n,a(n-1))schien immer 1 oder eine Primzahl zu sein. Die ersten Unterschiede sind ( 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, ...

Wenn wir nur die Einsen weglassen, erhalten wir die folgende Sequenz ( 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 bewies einige Jahre später die Primität jedes Elements in dieser Liste. Wie Sie sehen können, sind die Primzahlen gemischt und einige von ihnen erscheinen mehrmals. Es wurde auch nachgewiesen, dass die Sequenz unendlich viele verschiedene Primzahlen enthält. Weiterhin wird vermutet, dass alle ungeraden Primzahlen auftreten.

Da dieser Primärgenerator nicht konstruiert wurde, sondern einfach zufällig gefunden wurde, wird der Primärgenerator als "natürlich vorkommend" bezeichnet. Beachten Sie jedoch, dass sich dieser Generator in der Praxis auch nicht berechnen lässt. Wie sich herausstellt, erscheint eine Primzahl p erst nach (p–3)/2aufeinanderfolgenden Einsen. Trotzdem wird es Ihre Aufgabe sein, diesen Primärgenerator zu implementieren.

Herausforderung:

Schreiben Sie eine Funktion oder ein Programm, das die ersten nElemente der Sequenz druckt A137613(die Sequenz ohne die Einsen). Sie können die Eingabenummer n >= 0über STDIN, Befehlszeilenargument, Eingabeaufforderung oder Funktionsargument lesen . Geben Sie die ersten nElemente in einem beliebigen lesbaren Format an STDOUT aus oder geben Sie ein Array oder eine Liste mit diesen Werten zurück.

Das ist Code-Golf. Daher gewinnt der kürzeste Code.

Bestenliste:

Hier ist ein Stack-Snippet, um sowohl eine reguläre Rangliste als auch eine Übersicht der Gewinner nach Sprache zu generieren. Um sicherzustellen, dass Ihre Antwort angezeigt wird, beginnen Sie Ihre Antwort mit einer Überschrift. Verwenden Sie dazu die folgende Markdown-Vorlage:

# Language Name, N bytes

Wobei N die Größe Ihrer Einreichung ist. Wenn Sie Ihre Punktzahl verbessern, können Sie alte Punkte in der Überschrift behalten, indem Sie sie durchstreichen. Zum Beispiel:

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

Jakube
quelle
1
Während der Primärgenerator nicht konstruiert ist, implementieren Sie mithilfe der Rekursion effektiv eine Testdivision.
Orlp
Wenn a (1) = 7, warum beginnt die Sequenz nicht mit 7?
Feersum
3
@feersum, weil die Sequenz, mit der wir uns befassen,a(n)-a(n-1)
Maltysen
Kann nnull sein?
Sp3000,
1
@ jrenk Ich bin mir nicht sicher. Zähle es vielleicht als 2 Bytes (da du 2 Zeichen entfernst //) und erkläre es in deinem Beitrag. Wenn jemand mit Ihnen nicht einverstanden ist, können Sie Ihren Beitrag jederzeit bearbeiten.
Jakube,

Antworten:

19

Pyth, 14 13 Bytes

meaYhP+sY-5dQ

Verwendet, a(n) = Lpf(6 - n + sum(a(i) for i in range(1, n))wo der Lpfkleinste Primfaktor bedeutet.

Probieren Sie es hier online.

orlp
quelle
7

Python 3.5.0b1 +, 95 93 Bytes

Link zu Python 3.5.0b1 + Release

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

Eine direkte Implementierung der Wiederholung mit:

  • Unser guter Freund 1%xund
  • math.gcdim Gegensatz zu fractions.gcd.
Sp3000
quelle
Was macht 1%xdas? Nebenfrage: Wo finde ich eine Dokumentation des Versionsverlaufs von Python, der Betas enthält? Edit: Nevermind, fand es am Ende der Revisionshistorie .
mbomb007
@ mbomb007 Da x >= 1, den 1%xWert 0 zurück , wenn x == 1, 1 sonst (verwendet zu entscheiden , ob hinzufügen xzur Liste)
SP3000
5

Julia, 110 Bytes

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
Alex A.
quelle
Wow, eine perfekte 8k, schön: D
Beta Decay
1
Verwenden Sie n<2anstelle von n==1. Wenn Sie vorwärts statt rückwärts schauen, können Sie auch i=1und x=a(i)-a(i+=1)und dann println(-x)und verwenden -x>1, um die Negativität zu korrigieren, wodurch die Notwendigkeit eines separaten Inkrements von vermieden wird i. Und ist drei Bytes, während >=ist zwei ... aber dann können Sie verwenden, n<1||()anstatt n>=1&&()... und doch ist es nicht einmal an erster Stelle erforderlich (löschen Sie die Bedingung, n wird nie kleiner als 1 sein). Sie brauchen auch nicht die äußersten Klammern, wenn Sie ein (n) definieren. Mit diesen Änderungen sollten Sie mindestens 97 Byte erreichen.
Glen O
5

PHP, 101 96 99 98 77 72 Bytes

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


Verwendung:
Rufen Sie das Skript mit einem Argument auf: php -d error_reporting=0 script.php 30
Wenn Sie es testen möchten, müssen ;extension=php_gmp.dllSie das Kommentarzeichen in Ihrer php.ini entfernen
-> extension=php_gmp.dll
Soll ich die Erweiterung zu meiner Byteanzahl hinzufügen? Irgendwelche Gedanken?


Protokoll:
Dank Ismael Miguel wurden 3 Bytes gespeichert.
26 Bytes dank primo gespart.

jrenk
quelle
1
Sie können Ihr Eröffnungs-Tag auf kürzen <?und die Definition von entfernen $j.
Ismael Miguel
1
Ja, das zählt. Sie können diesen Zeilenumbruch jedoch entfernen. Das spart 1-2 Bytes, abhängig davon, wie Sie Ihre Codegröße gezählt haben.
Ismael Miguel
1
Kleinere Verbesserungen: Verwenden Sie <in $j<=$argv[1](druckt eine zu viele) (-1). Nicht $einitialisieren, $e+7stattdessen (-3) verwenden. Verwenden Sie for(;;)stattdessen while()die Vor- und Nachausdrücke (-2). Ersetzen echo$t.' ';$j++durch $j+=print"$t ", lassen Sie die Halterungen (-3) fallen. Ersetzen Sie if($t>1)mit 2>$t||(-2). Kombinieren Sie die Zuordnung zu $tmit der Bedingung, schalten Sie ||für or, lassen Sie die Klammern (-5) fallen. Bewegen Sie sich $argv[1]zum $jInkrement und verschieben Sie den gesamten Ausdruck in die forBedingung (-2). Wechseln Sie >=$j+=printzu -=print(-3). Schritt für Schritt: codepad.org/s6LNSPSM
primo
1
@primo danke für die nette erklärung! Wusste nicht, dass ich das alles machen könnte.
Juni
1
Noch ein paar: Kombiniere $e+7mit $e+=$t(-2). Nicht $iinitialisieren, ~++$istattdessen (-3) verwenden. codepad.org/fDIImajp
primo
4

Haskell, 51 Bytes

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

Beachten Sie, dass dies feine Funktion ist, die die ersten n Elemente zurückgibt.

Anstatt a(n)die Unterschiede zu berechnen und dann zu berechnen, berechnen wir sie d(n)und addieren sie, um sie zu erhalten a(n). (Diejenigen, die mit Haskell nicht vertraut sind, mögen protestieren, dass wir a(n)zuerst brauchen, um es zu bekommen d(n), aber eine faule Bewertung bringt uns natürlich um dieses Problem herum!)

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
Artelius
quelle
4

Pyth, 30 Bytes

Sehr schlecht golfen, kann erheblich reduziert werden. Definiert die rekursive Funktion im .fVordergrund , filtert zuerst n und bildet dann den Unterschied ab.

L?tb+KytbibK7m-yhdyd.ft-yhZyZQ

Probieren Sie es hier online .

Maltysen
quelle
Dies gibt die falsche Ausgabe fürn = 0
Sp3000
2
@ Sp3000 das ist ein Fehler in Pyth. Ich werde eine Pull-Anfrage stellen.
Maltysen
Fehler gefunden und behoben - Patch wird implementiert, sobald Github nicht mehr DDoS-fähig ist.
Isaacg
1
Hier ist es: meta.codegolf.stackexchange.com/questions/5318/… . Persönlich würde ich Bugfixes in Programmiersprachen als Antwort betrachten
Thomas Weller
2
@ThomasWeller Es hat irgendwie die ganze Sprache erreicht ...
isaacg
4

Julia, 69 67 Bytes

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

Dies ist eine einfache iterative Lösung des Problems. xist der Unterschied (der ist der gcd), und dann aktualisiere ich adurch Hinzufügen x.

Glen O
quelle
Ich denke, es druckt A231900 .
Alephalpha
@alephalpha - Ich denke, ich sehe den Fehler. Leicht zu reparieren. Dabei wurden sogar zwei Bytes gespart.
Glen O
3

JavaScript (ES6), 91

Rekursive gcd, iterative Hauptfunktion. Nicht so schnell.

Üblicher Hinweis: Testen Sie die Ausführung des Snippets in jedem EcmaScript 6-kompatiblen Browser (insbesondere nicht in Chrome und nicht in MSIE. Ich habe es in Firefox getestet, Safari 9 könnte funktionieren).

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>

edc65
quelle
3

Haskell, 74 71 66 Bytes

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

Habe den Trick hier benutzt: https://codegolf.stackexchange.com/a/39730/43318 , und ohne Punkt gemacht.

(Vorher: 71 Bytes)

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

Machen Sie zuerst die Sequenz von a und nehmen Sie dann die Unterschiede.

(Vorher: 74 Bytes)

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

Standardlistenfunktionen sowie die clevere Verwendung der Lambda-Funktion. Beachten Sie, dass dies 1 Byte kürzer ist als das offensichtlichere

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

Wenn wir die Importe nicht zählen, kann ich das auf 66 reduzieren.

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

PARI / GP, 60 Bytes

a(n)=a=7;i=1;while(n,if(1<d=gcd(i+=1,a),n-=1;print(d));a+=d)

Mehr oder weniger direkt aus der Definition a (n) - a (n-1) = gcd (n, a (n-1))

Ausgabe für a(20):

5
3
11
3
23
3
47
3
5
3
101
3
7
11
3
13
233
3
467
3
primo
quelle
2

C ++, 193 182 180 172 Bytes

Danke @Jakube - 8 Bytes bei der Ausgabe gespart.

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);}
EvgeniyZh
quelle
Sie können wahrscheinlich ein paar Bytes sparen, indem Sie eine Funktion definieren f, die ein Array mit den Ergebnissen zurückgibt. Auf diese Weise können Sie das Include, den Scanf und den Druck entfernen.
Jakube
2

Mathematica, 59 Bytes

For[i=j=1;a=7,i<=#,,d=GCD[++j,a];If[d>1,Print@d;i++];a+=d]&
Alephalpha
quelle