Primes de la spirale d'Ulam

17

La spirale d'Ulam est un sujet vraiment fascinant, mais déroutant, en mathématiques. Comment cela fonctionne en détail peut être trouvé ici , mais un bref résumé peut être expliqué comme suit:

Je commence par en écrire un, puis j'écris deux à droite. Au-dessus des deux, j'écris trois, et à gauche j'en écris quatre. Je continue ce schéma de cercle autour de 1 (et de tout nombre entre moi et 1) à l'infini (ou jusqu'à ce qu'on lui dise d'arrêter), formant un motif en spirale. (voir l'exemple ci-dessous)

L'objectif

Créez un programme qui accepte n (sera toujours un nombre impair supérieur à zéro) comme entrée en corrélation avec le nombre de lignes, puis imprime les valeurs des nombres premiers ligne par ligne de la spirale Ulam. Le formatage peut être de n'importe quelle façon, mais doit être lisible par l'homme et évident.

Par exemple, étant donné l'entrée 3, votre programme devrait sortir 5,3,2,7, car 3 lignes produisent la spirale suivante:

5 4 3 <-- first row has the primes 5 and 3
6 1 2 <-- second row has the prime 2
7 8 9 <-- third row has the prime 7

Comme c'est un golf de code, la réponse avec le moins d'octets gagne (peu importe son inefficacité)! Les failles standard ne sont pas acceptables.

Addison Crump
la source
Une virgule de fin est-elle autorisée? Ou mieux encore, l'espace séparé, par exemple `` `` 5 3 2 7 '' ``
Tom Carpenter
5
Tant qu'il est lisible par l'homme et peut me dire les nombres premiers, n'hésitez pas.
Addison Crump

Réponses:

8

Pyth, 20 octets

f}TPTsuC+R=hZ_GtyQ]]

Essayez-le en ligne: Démonstration

Ce code génère la spirale entièrement d'Ulam, connecte toutes les lignes et filtres pour les nombres premiers.

Explication:

f}TPTsuC+R=hZ_GtyQ]]   implicit: Z = 0
      u           ]]   reduce, start with G = [[]]
               tyQ     for H in [0, 1, ..., 2*input-2] do:
             _G           reverse the order of the lines
        +R=hZ             append Z + 1 at the end of each line, 
                          updating Z each time with the new value Z + 1
       C                  update G with the transposed of ^
                       this gives the Ulam's spiral
     s                 combine all lines to a big list of numbers
f                      filter for numbers T, which satisfy:
 }TPT                    T appears in the prime-factorization of T
                         (<==> T is prime)
Jakube
la source
6

MATLAB, 48

a=fliplr(spiral(input(''))');disp(a(isprime(a)))

Fondamentalement, cela crée une spirale de la taille requise (demandée à l'utilisateur), puis l'organise de sorte qu'elle apparaisse dans le bon ordre de ligne. Ceci est stocké dans un fichier. Ensuite, il affiche toutes les valeurs de a qui sont premières.

Comme vous avez dit tout format lisible, j'ai enregistré un octet et j'ai opté pour la sortie par défaut de disp () qui est (dans votre cas de test, n = 3):

 5
 3
 2
 7

En prime, cela fonctionne pour tout n> 0, y compris les nombres pairs. Par exemple, la sortie pour n = 10 est:

97
61
59
37
31
89
67
17
13
 5
 3
29
19
 2
11
53
41
 7
71
23
43
47
83
73
79
Tom Carpenter
la source
1
Très agréable! Bon à savoir cette spiralfonction
Luis Mendo
6

CJam, 42 33 octets

Xali(2*{_W%zY@,Y+:Y,>a+}*e_{mp},`

Essayez-le en ligne

La dernière version comprend des améliorations substantielles suggérées par @Martin.

La méthode de construction de la spirale consiste, à chaque étape, à faire pivoter la matrice que nous avons jusqu'à présent de 90 degrés et à ajouter une ligne avec des nombres supplémentaires. C'est répété plusieurs (n / 2) * 4fois.

Les valeurs de la matrice résultante sont ensuite filtrées pour être des nombres premiers.

Explication:

Xa    Push initial matrix [1].
li    Get input and convert to int.
(2*   Calculate 2*(n-1), which is the number of rotations and row additions needed.
{     Start rotation loop.
  _     Copy current matrix for getting number of rows later.
  W%    Reverse the order of the rows...
  z     ... and transpose the matrix. The combination produces a 90 degree rotation.
  Y     Get next value from variable Y (which is default initialized to 2).
  @,    Rotate previous matrix to top, and get number of rows. This is the number
        of columns after the 90 degree rotation, meaning that it's the length of
        the row to be added.
  Y+    Add first value to row length to get end value.
  :Y    Save it in Y. This will be the first value for next added row.
  ,     Create list of values up to end value.
  >     Slice off values up to start value, leaving only the new values to be added.
  a+    Wrap the new row and add it to matrix.
}*    End of rotation loop.
e_    Flatten matrix into list.
{mp}, Filter list for primes.
`     Convert list to string for output.
Reto Koradi
la source
Pourrait 2/4*être remplacé par 2*, ou l'avez-vous laissé comme ça exprès?
ETHproductions
@ETHproductions Ce n'est pas équivalent car c'est une division entière. Par exemple, pour l'entrée 3, le résultat doit être 4. En fait, maintenant que j'y pense, je crois qu'il y a un octet à enregistrer. (2*devrait être correct.
Reto Koradi
5

Mathematica 223

Cela s'approprie le code de Kuba pour une spirale Ulam. C'est pourquoi je le soumets en tant que wiki communautaire. Je l'ai simplement joué au golf et sélectionné les nombres premiers, qui sont répertoriés par la ligne dans laquelle ils résident.

r=Range;i=Insert;t=Transpose;s@n_:=#~Select~PrimeQ&/@Nest[With[{d=Length@#,l=#[[-1,-1]]},
Composition[i[#,l+3d+2+r[d+2],-1]&,t@i[t@#,l+2d+1+r[d+1],1]&,i[#,l+d+r[d+1,1,-1],1]&,
t@i[t@#,l+r[d,1,-1],-1] &][#,15]]&,{{1}},(n-1)/2]

Exemple

 s{15]

{{197, 193, 191}, {139, 137}, {199, 101, 97, 181}, {61, 59, 131}, {103, 37, 31, 89, 179}, {149, 67, 17, 13}, {5, 3, 29}, {151, 19, 2, 11, 53, 127}, {107, 41, 7}, {71, 23}, {109, 43, 47, 83, 173}, {73, 79}, {113}, {157, 163, 167}, {211, 223}}

Pour améliorer l'affichage:

 %// MatrixForm

matrice

DavidC
la source
4

Mathematica, 118 octets

f=Permute[Range[#*#],Accumulate@Take[Join[{#*#+1}/2,Flatten@Table[(-1)^j i,{j,#},{i,{-1,#}},{j}]],#*#]]~Select~PrimeQ&

Cela génère la spirale Ulam sous forme linéaire en notant que la position de chaque nombre suivant peut être accumulée comme

{(n*n + 1)/2, +1, -n, -1, -1, +n, +n, +1, +1, +1, -n, -n, -n, ...}

c'est à dire partir du centre, puis se déplacer 1 à droite, 1 en haut, 2 à gauche, 2 en bas, 3 à droite, 3 en haut, ...

Production:

In[515]:= f[5]
Out[515]= {17,13,5,3,19,2,11,7,23}

la source
1

Javascript, 516 363 304 276 243 240 octets

Ma solution ne crée pas une matrice dense avec la Spirale, au lieu de cela, elle retourne l'index qui correspond au nombre donné dans la matrice d'Ulam de l'ordre donné. Il parcourt donc les nombres entre 2 et M * M et crée un tableau de nombres premiers avec l'idx donné par le fn ulamIdx

M=15;
$=Math;
_=$.sqrt;
/**
 * Return M*i+j (i.e. lineal or vector idx for the matrix) of the Ulam Matrix for the given integer
 * 
 * Each Segment (there are 4 in each round) contains a line of consecutive integers that wraps the 
 * inner Spiral round. In the foCowing example Segments are: {2,3}, {4,5},
 * {6,7}, {8,9}, {a,b,c,d}, {e,f,g,h}, {i,j,k,l}, {m,n,o,p}  
 *            
 *    h g f e d
 *    i 5 4 3 c
 *    j 6 1 2 b
 *    k 7 8 9 a 
 *    l m n o p
 * 
 * @param n integer The integer which position in the Matrix we want.
 * @param M integer Matrix Order. 
 */
/*
 * m: modulus representing step in segment in current spirtal round
 * v: Step in current spiral round, i.e. n - (inner spirals greatest num.)
 * s: the current Segment one of [1, 2, 3, 4] that represents the current spiral round 
 * L: Segment Length (Current spiral round Order - 1)
 * B: inner Spiral Order, for trib¿vial case 1 it's -1 special case handled differently.
 * C: relative line (row or column) corresponding to n in current spiral Round 
 * R: relative line (column or row) corresponding to n in current spiral Round
 * N: Curren (the one that contains n) Spiral (matrix) round Order
 * D: Difference between M and the current Spiral round order.
 */

/**
 * Runs the loop for every integer between 2 and M*M
 * Does not check sanity for M, that should be odd.
 */
r=[];
for (x = 2; x < M * M; x++) {
    p=1;
    // Is Prime?
    for (k = 2; p&&k <= _(x); k++)
        if (x % k==0) p=0;
    if (p) {
        B = $.floor(_(x - 1));
        B=B&1?B:B-1;
        N = B + 2;
        D = (M - N) / 2;
            v = x - B * B;
            L = B + 1;
            s = $.ceil(v / L);
            m = v % L || L;
            C = D + (s < 3 ? N - m : 1 + m);
            R = s&2 ? D + 1 : D + N;
            w= s&1 ? M * C + R : M * R + C;
        // /*uncomment to debug*/ console.log("X:" + x + ": " + ((s&1) ? [C, R].join() : [R, C].join()));
        r[w] = x;
    }
}
alert(r);

Minified ressemble à ceci:

for(M=15,$=Math,_=$.sqrt,r=[],x=2;x<M*M;x++){for(p=1,k=2;p&&k<=_(x);k++)x%k==0&&(p=0);p&&(B=$.floor(_(x-1)),B=1&B?B:B-1,N=B+2,D=(M-N)/2,v=x-B*B,L=B+1,s=$.ceil(v/L),m=v%L||L,C=D+(s<3?N-m:1+m),R=2&s?D+1:D+N,w=1&s?M*C+R:M*R+C,r[w]=x)}alert(r);

Pour l'entrée 15, la sortie est:

,,,,,,,,,,,,,,,, 197 ,,,, 193,, 191 ,,,,,,,,,,,,,,,, 139,, 137 ,,,,, , 199,, 101 ,,,, 97 ,,,,,,,, 181 ,,,,,,,, 61,, 59 ,,,, 131 ,,,, 103,, 37 ,,,,,, 31,, 89,, 179,, 149,, 67,, 17 ,,,, 13 ,,,,,,,,,,,, 5,, 3,, 29 ,,,,,, 151 ,,, , 19 ,,, 2,11,, 53,, 127 ,,,, 107,, 41,, 7 ,,,,,,,,,,,, 71 ,,,, 23 ,,,,,,,, ,,, 109,, 43 ,,,, 47 ,,,, 83,, 173 ,,,, 73 ,,,,,, 79 ,,,,,,,,,, 113 ,,,,,,, ,,,,, 157 ,,,,,, 163 ,,,, 167 ,,,, 211 ,,,,,,,,,,,, 223

juanmf
la source
C'était pas mal de compression. Pouvez-vous expliquer votre code d'origine et vos modifications?
Addison Crump
J'ai enlevé quelques parenthèses inutiles. Et réalisé que uI () avait 4 conditions avec des blocs similaires. Chacune avec 3 lignes qui ont généré Row et Collumn pour le segment en cours (voir docblock principal) donc je remplace ces 4 blocs par des lignes ll & llt et la ligne de retour décide si llt est une ligne ou une colonne. S & 2 est vrai pour s dans (3,2) (segments supérieur et gauche); s <3, pour s dans (1,2) droite et supérieure. S & 1, pour s dans (1,3) déterminera si les valeurs dans ll & llt sont row & col ou col & row et M (ordre en spirale) × row + col preventes index superposés (comme rectifier la matrice mais avec un mauvais idx linéaire, la correction serait besoin de ll-1
juanmf
Dans la boucle principale (run ()) seulement si i est premier (dont fn a été réduit comme jamais besoin de tester pour <2 ni% 1) il demande l'index de i (ll, llt) dans la spirale, ce qui est corrigé. Imprimez ensuite le tableau de résultats.
juanmf
Il existe 3 matrices conceptuellement importantes. Inner, curret & M. Utile pour calculer la ligne absolue et le col. La soustraction de l'intérieur à n nous laisse avec un int relatif en courant (celui dans lequel n tombe) en spirale. Et la différence entre M et l'ordre actuel joue comme décalage pour la ligne et le col dans le tour en cours pour obtenir les absolus.
juanmf
364 -> 240 en écrivant la logique fn en ligne et en supprimant les tests inutilisés.
juanmf