Un premier générateur naturel


42

Il existe un assez grand nombre de fonctions génératrices principales. La plupart d'entre elles sont construites et sont basées sur le tamis d'Eratosthène, la fonction de Möbius ou le théorème de Wilson et sont généralement impossibles à calculer en pratique. Mais il y a aussi des générateurs, qui ont une structure très facile et qui ont été trouvés par accident.

En 2003, Stephen Wolfram a exploré une classe d’équations de récurrence imbriquée dans le cadre d’une expérience informatique en direct à l’Université d’été NKS. Un groupe de personnes autour de Matthew Frank a poursuivi avec d'autres expériences et a découvert une propriété intéressante de la simple récurrence

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

avec la valeur de départ de a(1) = 7. La différence a(n) - a(n-1) = gcd(n,a(n-1))semblait toujours être 1 ou un prime. Les premières différences sont les suivantes ( 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, ...

Si nous omettons uniquement les 1, nous obtenons la séquence suivante ( 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 a prouvé la primauté de chaque élément de cette liste quelques années plus tard. Comme vous pouvez le constater, les nombres premiers sont mélangés et certains d’entre eux apparaissent plusieurs fois. Il a également été prouvé que la séquence comprenait une infinité de nombres premiers distincts. De plus, on suppose que tous les nombres premiers impairs apparaissent.

Parce que ce générateur principal n'a pas été construit mais simplement trouvé par accident, le générateur principal s'appelle "se produisant naturellement" Mais notez que, dans la pratique, ce générateur est également très difficile à calculer. Il se trouve que le nombre premier p apparaît uniquement après (p–3)/2des 1 consécutifs. Néanmoins, l'implémentation de ce premier générateur sera votre tâche.

Défi:

Ecrivez une fonction ou un programme qui affiche les premiers néléments de la séquence A137613(la séquence sans les 1). Vous pouvez lire le numéro d'entrée n >= 0via STDIN, un argument de ligne de commande, une invite ou un argument de fonction. Exportez les premiers néléments dans n'importe quel format lisible vers STDOUT ou renvoyez un tableau ou une liste avec ces valeurs.

C'est du code-golf. Par conséquent, le code le plus court gagne.

Classement:

Voici un extrait de pile permettant de générer à la fois un classement régulier et un aperçu des gagnants par langue. Pour vous assurer que votre réponse apparaît, commencez votre réponse par un titre, en utilisant le modèle Markdown suivant:

# Language Name, N bytes

où N est la taille de votre soumission. Si vous améliorez votre score, vous pouvez conserver les anciens scores en les effaçant. Par exemple:

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


1
Bien que le générateur principal ne soit pas construit, vous implémentez efficacement une division d'essai en utilisant la récursivité.
Orlp

Si a (1) = 7, pourquoi la séquence ne commence-t-elle pas par 7?
Feersum

3
@feersum parce que la séquence qui nous intéresse esta(n)-a(n-1)
Maltysen

Peut nêtre zéro?
Sp3000

1
@jrenk Pas sûr. Peut-être le compter comme 2 octets (puisque vous supprimez 2 caractères //) et l'expliquer dans votre soumission. Si quelqu'un n'est pas d'accord avec vous, vous pouvez toujours modifier votre message.
Jakube

Réponses:


19

Pyth, 14 à 13 octets

meaYhP+sY-5dQ

Utilisations a(n) = Lpf(6 - n + sum(a(i) for i in range(1, n))Lpfsignifie le moins facteur premier.

Essayez-le ici en ligne.


7

Python 3.5.0b1 +, 95 93 octets

Lien vers 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

Une implémentation directe de la récurrence, comprenant:

  • Notre bon ami 1%x, et
  • math.gcd, par opposition à fractions.gcd.

Que fait 1%x-il? Question annexe: où se trouve la documentation de l'historique des révisions de Python incluant les bêtas? Edit: Nevermind, trouvé au bas de l' historique de révision .
mbomb007

@ mbomb007 Depuis x >= 1, 1%xretourne 0 si x == 1, 1 sinon (utilisé pour décider d'ajouter ou non xà la liste)
Sp3000

5

Julia, 110 octets

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

Wow, un 8k parfait, sympa: D
Beta Decay

1
Utilisez n<2au lieu de n==1. De plus, si vous regardez en avant au lieu d’arrière, vous pouvez utiliser i=1et x=a(i)-a(i+=1), puis, println(-x)et -x>1pour corriger de la négativité, évitant ainsi l’incrément de i. Et est trois octets, alors que >=est deux ... mais alors, vous pouvez utiliser n<1||()plutôt que n>=1&&()... et pourtant, il n'est même pas nécessaire en premier lieu (supprimez le conditionnel, n ne sera jamais inférieur à 1). Vous n'avez également pas besoin des crochets les plus à l'extérieur pour définir un (n). Avec ces modifications, vous devriez au moins descendre à 97 octets.
Glen O

5

PHP, 101 96 99 98 77 72 octets

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


Utilisation:
Appelez le script avec un argument: php -d error_reporting=0 script.php 30
Si vous voulez le tester, vous devez supprimer le commentaire ;extension=php_gmp.dlldans votre php.ini
-> extension=php_gmp.dll
Devrais-je ajouter l'extension à mon nombre d'octets? Des pensées?


Journal:
3 octets enregistrés grâce à Ismael Miguel.
Sauvegardé 26 octets grâce à primo.


1
Vous pouvez raccourcir votre balise d'ouverture <?et supprimer la définition de $j.
Ismael Miguel

1
Oui ça compte. Mais vous pouvez supprimer cette nouvelle ligne. Ce qui permettra d'économiser 1-2 octets, en fonction de la façon dont vous avez calculé la taille de votre code.
Ismael Miguel

1
Améliorations mineures: Utiliser <dans $j<=$argv[1](en imprimer un de trop) (-1). Laissez $enon initialisé, utilisez $e+7plutôt (-3). Utilisez for(;;)au lieu de while(), en utilisant les expressions avant et après (-2). Remplacer echo$t.' ';$j++par $j+=print"$t ", lâcher les crochets (-3). Remplacez if($t>1)par 2>$t||(-2). Combinez l’affectation de $tavec le conditionnel, changez ||pour or, supprimez les crochets (-5). Déplacer $argv[1]vers l' $jincrément, déplace l'intégralité de l'expression vers le forconditionnel (-2). Changer >=$j+=printen -=print(-3). Étape par étape: codepad.org/s6LNSPSM
primo

1
@primo merci pour la belle explication! Je ne savais pas que je pouvais faire tout ça.
Jrenk

1
Un peu plus: Combinez $e+7avec $e+=$t(-2). Laissez $inon initialisé, utilisez ~++$iplutôt (-3). codepad.org/fDIImajp
Primo

4

Haskell, 51 octets

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

Notez que fc'est une fonction qui retournera les n premiers éléments.

Plutôt que de a(n)calculer les différences d(n)puis de les calculer, nous les calculons et les additionnons pour les obtenir a(n). (Ceux qui ne sont pas familiers avec Haskell peuvent protester contre le fait que nous avons besoin d’ a(n)abord pour obtenir d(n), mais bien sûr, une évaluation paresseuse nous aide à résoudre ce problème!)

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 octets

Très mal joué au golf, peut être considérablement réduit. Définit la fonction récursive au premier plan, filtre le .fpremier-n, puis mappe la différence.

L?tb+KytbibK7m-yhdyd.ft-yhZyZQ

Essayez-le ici en ligne .


Cela donne une mauvaise sortie pourn = 0
Sp3000

2
@ Sp3000 c'est un bogue en Pyth. Je vais mettre dans une demande de traction.
Maltysen

Bug trouvé et corrigé - le correctif sera mis en œuvre une fois que github ne sera plus en mode DDoS.
isaacg

1
La voici: meta.codegolf.stackexchange.com/questions/5318/… . Personnellement, je considérerais les corrections de bugs dans les langages de programmation comme une réponse
Thomas Weller

2
@ThomasWeller Il a en quelque sorte atteint toute la langue ...
isaacg

4

Julia, 69 67 octets

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

C'est une solution simple et itérative au problème. xest la différence (qui est le gcd), puis je mets à jour aen ajoutant x.


Je pense qu'il imprime A231900 .
alephalpha

@alephalpha - Je pense que je vois l'erreur. Facilement réparé. Même rasé deux octets dans le processus.
Glen O

3

JavaScript (ES6), 91

Gcd récursif, fonction principale itérative. Pas si vite.

Note habituelle: testez l’exécution de l’extrait de code sur n’importe quel navigateur conforme à EcmaScript 6 (notamment pas Chrome ni MSIE. J’ai testé sur Firefox, Safari 9 pourrait fonctionner)

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 octets

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

Utilisé le truc ici: https://codegolf.stackexchange.com/a/39730/43318 , et rendu sans point.

(Previous: 71 bytes)

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

Commencez par faire la séquence de a, puis prenez les différences.

(Précédent: 74 octets)

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

Fonctions de liste standard, plus utilisation intelligente de la fonction lambda. Notez que c'est un octet plus court que le plus évident

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

Si nous ne comptons pas les importations, je peux le réduire à 66.

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

3

PARI / GP, 60 octets

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

Tiré plus ou moins directement de la définition a - (n) - a (n-1) = gcd (n, a (n-1))

Sortie pour 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 octets

Merci @Jakube - 8 octets enregistrés en sortie.

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

Vous pouvez probablement économiser quelques octets en définissant une fonction f, qui renvoie un tableau avec les résultats. De cette façon, vous pouvez supprimer l'include, le scanf et l'impression.
Jakube

2

Mathematica, 59 octets

For[i=j=1;a=7,i<=#,,d=GCD[++j,a];If[d>1,Print@d;i++];a+=d]&
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.