Primes of Ulam's Spiral


17

La spirale di Ulam è un argomento davvero affascinante, ma sconcertante, in matematica. Come funziona in dettaglio può essere trovato qui , ma un breve riassunto può essere spiegato come segue:

Comincio scrivendone uno, quindi scrivo un due a destra. Sopra i due scrivo un tre e alla sinistra scrivo quattro. Continuo questo schema di cerchi intorno a 1 (e tutti i numeri tra me e 1) all'infinito (o fino a quando non viene detto di smettere), formando un motivo a spirale. (vedi esempio sotto)

L'obiettivo

Crea un programma che accetta n (sarà sempre un numero dispari maggiore di zero) come input correlato al numero di righe, quindi stampa i valori dei numeri primi riga per riga della spirale di Ulam. La formattazione può essere di qualsiasi moda, ma deve essere leggibile e ovvia.

Ad esempio, dato l'ingresso 3, l'output del programma dovrebbe essere eseguito 5,3,2,7, poiché 3 righe producono la seguente spirale:

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

Poiché si tratta di un codice golf, vince la risposta con il minor numero di byte (non importa quanto inefficiente)! Le lacune standard non sono accettabili.


È consentita una virgola finale? O meglio, spazio separato, ad es. `` 5 3 2 7``
Tom Carpenter,

5
Finché è leggibile dall'uomo e può dirmi i numeri primi, sentiti libero.
Addison Crump,

Risposte:


8

Pyth, 20 byte

f}TPTsuC+R=hZ_GtyQ]]

Provalo online: dimostrazione

Questo codice genera la spirale di Ulam, collega tutte le linee e i filtri per i numeri primi.

Spiegazione:

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)

6

MATLAB, 48

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

Fondamentalmente questo crea una spirale della dimensione richiesta (richiesta dall'utente), quindi la organizza in modo che appaia nell'ordine di riga corretto. Questo è memorizzato in a. Successivamente visualizza tutti i valori in a che sono primi.

Come hai detto qualsiasi formato leggibile, ho salvato un byte e ho scelto l'output predefinito di disp () che è (nel tuo caso di test, n = 3):

 5
 3
 2
 7

Come bonus aggiuntivo, funziona con qualsiasi n> 0, compresi i numeri pari. Ad esempio, l'output per n = 10 è:

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

1
Molto bella! Buono a sapersi quella spiralfunzione
Luis Mendo,

6

CJam, 42 33 byte

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

Provalo online

L'ultima versione include miglioramenti sostanziali suggeriti da @Martin.

Il metodo per costruire la spirale è, in ogni passaggio, ruotare la matrice che abbiamo finora di 90 gradi e aggiungere una riga con numeri aggiuntivi. Questo è ripetuto (n / 2) * 4volte.

I valori nella matrice risultante vengono quindi filtrati per essere numeri primi.

Spiegazione:

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.

Potrebbe 2/4*essere sostituito da 2*, o l'hai lasciato così apposta?
ETHproductions

@ETHproductions Non è equivalente perché è una divisione intera. Ad esempio, per l'ingresso 3, il risultato deve essere 4. In realtà, ora che ci penso, credo che ci sia un byte da salvare. (2*dovrebbe essere corretto.
Reto Koradi,

5

Mathematica 223

Questo si appropria del codice di Kuba per una spirale di Ulam. Ecco perché lo sto inviando come wiki della community. Ho semplicemente giocato a golf e selezionato i numeri primi, che sono elencati in base alla riga in cui risiedono.

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]

Esempio

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

Per migliorare la visualizzazione:

 %// MatrixForm

matrice


4

Mathematica, 118 byte

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

Questo genera la spirale di Ulam in forma lineare osservando che la posizione di ciascun numero successivo può essere accumulata come

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

cioè inizia dal centro, quindi sposta 1 a destra, 1 in alto, 2 a sinistra, 2 in basso, 3 a destra, 3 in alto, ...

Produzione:

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

1

Javascript, 516 363 304 276 243 240 byte

La mia soluzione non crea una matrice densa con la Spirale, ma restituisce l'indice che corrisponde al numero dato nella Matrice di Ulam di un dato ordine. Quindi scorre tra i numeri tra 2 e M * M e crea una matrice di numeri primi con l'idx dato da 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 si presenta così:

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

Per l'ingresso 15 l'uscita è:

,,,,,,,,,,,,,,,, 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


È stata una certa compressione. Puoi spiegare il tuo codice originale e le tue modifiche?
Addison Crump,

Ho rimosso alcune parentesi inutili. E ho capito che uI () aveva 4 condizionali con blocchi simili. Ciascuno con 3 righe che hanno generato Row e Collumn per il segmento corrente (vedi blocco documenti principale), quindi sostituisco questi 4 blocchi con righe ll & llt e la linea di ritorno decide se llt è riga o colonna. S & 2 è vero per s in (3,2) (segmenti superiore e sinistro); s <3, per s in (1,2) destra e superiore. S & 1, per s in (1,3) determinerà se i valori in ll & llt sono row & col o col & row e M (ordine a spirale) × row + col impedisce gli indici sovrapposti (come la matrice rettificante ma con un idx lineare errato, la correttezza sarebbe need ll-1
juanmf,

Nel ciclo principale (run ()) solo se i è primo (il cui fn è stato ridotto in quanto non è mai stato necessario testare <2 né% 1) richiede l'indice i (ll, llt) nella spirale, che viene rettificato. Quindi basta stampare l'array dei risultati.
juanmf,

Ci sono 3 matrici concettualmente importanti. Inner, curret & M. Utile per il calcolo di righe assolute e col. La sottrazione interna ad n ci lascia con un relativo int nella spirale corrente (quella in cui n cade). E la differenza tra l'ordine di M e quello attuale gioca come offset per riga e colonna nel round corrente per ottenere quelli assoluti.
juanmf,

364 -> 240 scrivendo la logica fn in linea e rimuovendo i test non utilizzati.
juanmf,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.