Primes of Ulam's Spiral

17

Spirala Ulama to naprawdę fascynujący, ale zagadkowy temat w matematyce. Jak to działa szczegółowo można znaleźć tutaj , ale krótkie podsumowanie można wyjaśnić w następujący sposób:

Zaczynam od napisania jednego, a potem dwa po prawej stronie. Powyżej dwóch piszę trójkę, a po lewej stronie cztery. Kontynuuję ten wzór krążenia wokół 1 (i dowolnych liczb między mną a 1) w nieskończoność (lub dopóki nie każę przestać), tworząc spiralny wzór. (patrz przykład poniżej)

Cel

Stwórz program, który przyjmuje n (zawsze będzie liczbą nieparzystą większą od zera) jako dane wejściowe, które korelują z liczbą wierszy, a następnie wypisuje wartości liczb pierwszych rząd po rzędzie spirali Ulama. Formatowanie może być dowolne, ale musi być czytelne dla człowieka i oczywiste.

Na przykład, biorąc pod uwagę wejście 3, twój program powinien wypisać 5,3,2,7, ponieważ 3 rzędy tworzą następującą spiralę:

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

Ponieważ jest to golf golfowy, wygrywa odpowiedź z najmniejszą liczbą bajtów (bez względu na to, jak mało wydajna)! Standardowe luki są niedopuszczalne.

Addison Crump
źródło
Czy dozwolony jest przecinek końcowy? Lub jeszcze lepiej, oddzielone spacją, np. `` 5 3 2 7 ''
Tom Carpenter,
5
Tak długo, jak jest czytelny dla człowieka i może mi powiedzieć liczby pierwsze, nie krępuj się.
Addison Crump,

Odpowiedzi:

8

Pyth, 20 bajtów

f}TPTsuC+R=hZ_GtyQ]]

Wypróbuj online: demonstracja

Ten kod generuje w pełni spiralę Ulama, łączy wszystkie linie i filtry dla liczb pierwszych.

Wyjaśnienie:

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
źródło
6

MATLAB, 48

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

Zasadniczo tworzy to spiralę o wymaganym rozmiarze (żądanym od użytkownika), a następnie ustawia ją w taki sposób, aby pojawiała się we właściwej kolejności wierszy. Jest to przechowywane w. Następnie wyświetla wszystkie wartości w pierwszej.

Jak powiedziałeś, każdy możliwy do odczytania format, zapisałem bajt i wybrałem domyślną wartość wyjściową disp (), którą jest (w twoim przypadku testowym n = 3):

 5
 3
 2
 7

Jako dodatkowy bonus działa dla dowolnego n> 0, w tym liczb parzystych. Na przykład dane wyjściowe dla n = 10 to:

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
źródło
1
Bardzo dobrze! Dobrze wiedzieć, że ta spiralfunkcja
Luis Mendo,
6

CJam, 42 33 bajty

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

Wypróbuj online

Najnowsza wersja zawiera znaczne ulepszenia sugerowane przez @Martin.

Metodą budowy spirali jest obrócenie macierzy o 90 stopni na każdym etapie i dodanie wiersza z dodatkowymi liczbami. To się powtarza(n / 2) * 4 .

Wartości w wynikowej macierzy są następnie filtrowane pod kątem liczb pierwszych.

Wyjaśnienie:

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
źródło
Może 2/4*być zastąpiony przez 2*, czy też specjalnie go tak zostawiłeś?
ETHproductions
@ETHproductions Nie jest to równoważne, ponieważ jest to podział na liczby całkowite. Na przykład dla danych wejściowych 3 wynik musi wynosić 4. Właściwie teraz, kiedy o tym myślę, uważam, że istnieje bajt do zapisania. (2*powinno być poprawne.
Reto Koradi,
5

Mathematica 223

To przywłaszcza kod Kuby spirali Ulama. Dlatego przesyłam go jako wiki społeczności. Po prostu grałem w golfa i wybrałem liczby pierwsze, które są wymienione według rzędu, w którym się znajdują.

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]

Przykład

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

Aby poprawić wyświetlanie:

 %// MatrixForm

matryca

DavidC
źródło
4

Mathematica, 118 bajtów

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

Generuje to spiralę Ulama w postaci liniowej, zauważając, że położenie każdej kolejnej liczby może być kumulowane jako

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

tzn. zacznij od środka, a następnie przesuń 1 w prawo, 1 w górę, 2 w lewo, 2 w dół, 3 w prawo, 3 w górę, ...

Wynik:

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

źródło
1

JavaScript, 516 363 304 276 243 240 bajtów

Moje rozwiązanie nie tworzy gęstej macierzy ze Spiralą, zamiast tego zwraca indeks, który odpowiada podanej liczbie w Matrycy Ulama dla danego rzędu. I tak iteruje liczby od 2 do M * M i tworzy tablicę liczb pierwszych o idx podanym przez 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 wygląda następująco:

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

Dla wejścia 15 wyjście jest następujące:

,,,,,,,,,,,,,,,,, 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
źródło
To była całkiem spora kompresja. Czy możesz wyjaśnić swój oryginalny kod i zmiany?
Addison Crump,
Usunąłem kilka bezużytecznych wsporników. I zdałem sobie sprawę, że uI () miał 4 warunki warunkowe z podobnymi blokami. Każdy z 3 liniami, które wygenerowały wiersz i kolumnę dla bieżącego segmentu (patrz główny blok dokumentu), więc zastępuję te 4 bloki liniami ll i llt, a linia zwrotna decyduje, czy llt jest wierszem czy kolumną. S & 2 jest prawdziwe dla s w (3,2) (górny i lewy segment); s <3, dla s w (1,2) prawej i górnej. S & 1, dla s w (1,3) określi, czy wartości w ll i llt są wierszami i colami lub colami i wierszami, a M (kolejność spiralna) × row + col zapobiega nakładaniu się indeksów (podobnie jak macierz rektyfikacyjna, ale z niewłaściwym idxem liniowym) need ll-1
juanmf
W głównej pętli (run ()) tylko wtedy, gdy i jest liczbą pierwszą (która fn została zmniejszona, ponieważ nigdy nie trzeba testować dla <2 ani% 1), prosi o indeks i (ll, llt) w spirali, która jest korygowana. Następnie wystarczy wydrukować tablicę wyników.
juanmf
Istnieją 3 koncepcyjnie ważne matryce. Wewnętrzna, curret i M. Przydatna do obliczania bezwzględnego wiersza i kol. Odejmowanie wartości wewnętrznej od n pozostawia nam okrągłą spiralę w stosunku do int w prądzie (tym, w którym n spada). I różnica między kolejnością M i porządkiem prądu odgrywa rolę przesunięcia dla wiersza i kolumny w bieżącej rundzie, aby uzyskać absolutne.
juanmf
364 -> 240, pisząc logikę fn i usuwając nieużywane testy.
juanmf