Bilangan Primer dari Ulam's Spiral

17

Ulam's spiral adalah topik matematika yang benar - benar menarik, namun membingungkan. Cara kerjanya secara detail dapat ditemukan di sini , tetapi ringkasan singkat dapat dijelaskan sebagai berikut:

Saya mulai dengan menulis satu, lalu saya menulis dua di sebelah kanannya. Di atas keduanya, saya menulis tiga, dan di sebelah kiri saya menulis empat. Saya melanjutkan pola berputar-putar ini di sekitar 1 (dan angka apa pun di antara saya dan 1) tanpa batas (atau sampai disuruh berhenti), membentuk pola spiral. (lihat contoh di bawah)

Objektif

Buatlah program yang menerima n (akan selalu menjadi angka ganjil lebih besar dari nol) sebagai input yang berkorelasi dengan jumlah baris, lalu cetak nilai-nilai bilangan prima demi baris spiral Ulam. Format dapat berupa mode apa pun, tetapi harus dapat dibaca dan jelas oleh manusia.

Misalnya, mengingat input 3, program Anda harus menampilkan 5,3,2,7, karena 3 baris menghasilkan spiral berikut:

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

Karena ini adalah kode golf, jawaban dengan byte paling sedikit menang (tidak peduli seberapa tidak efisien)! Celah standar tidak dapat diterima.

Addison Crump
sumber
Apakah koma trailing diperbolehkan? Atau lebih baik lagi, ruang terpisah, misalnya `` `5 3 2 7```
Tom Carpenter
5
Selama itu bisa dibaca manusia dan bisa memberi tahu saya bilangan prima, jangan ragu.
Addison Crump

Jawaban:

8

Pyth, 20 byte

f}TPTsuC+R=hZ_GtyQ]]

Cobalah online: Demonstrasi

Kode ini menghasilkan spiral Ulam sepenuhnya, menghubungkan semua garis dan filter untuk bilangan prima.

Penjelasan:

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
sumber
6

MATLAB, 48

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

Pada dasarnya ini menciptakan spiral dengan ukuran yang diperlukan (diminta dari pengguna), kemudian mengaturnya sehingga muncul dalam urutan baris yang benar. Ini disimpan dalam a. Selanjutnya ini menampilkan semua nilai yang prima.

Seperti yang Anda katakan format yang dapat dibaca, saya menyimpan byte dan pergi untuk output default disp () yang (dalam kasus pengujian Anda, n = 3):

 5
 3
 2
 7

Sebagai bonus tambahan, ini bekerja untuk n> 0, termasuk angka genap. Sebagai contoh, output untuk n = 10 adalah:

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
sumber
1
Sangat bagus! Senang mengetahui spiralfungsi itu
Luis Mendo
6

CJam, 42 33 byte

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

Cobalah online

Versi terbaru mencakup peningkatan substansial yang disarankan oleh @Martin.

Metode untuk membangun spiral adalah, pada setiap langkah, memutar matriks yang kita miliki sejauh ini sejauh 90 derajat, dan menambahkan baris dengan angka tambahan. Ini berulang (n / 2) * 4kali.

Nilai-nilai dalam matriks yang dihasilkan kemudian disaring untuk dijadikan bilangan prima.

Penjelasan:

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
sumber
Bisa 2/4*diganti oleh 2*, atau Anda sengaja membiarkannya seperti itu?
ETHproduksi
@ ETHproductions Itu tidak setara karena ini adalah divisi integer. Misalnya, untuk input 3, hasilnya harus 4. Sebenarnya, sekarang setelah saya pikirkan, saya yakin ada byte yang harus disimpan. (2*harus benar.
Reto Koradi
5

Mathematica 223

Ini sesuai dengan kode Kuba untuk spiral Ulam. Itu sebabnya saya mengirimkannya sebagai wiki komunitas. Saya hanya bermain golf dan memilih bilangan prima, yang terdaftar pada baris di mana mereka tinggal.

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]

Contoh

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

Untuk meningkatkan tampilan:

 %// MatrixForm

matriks

DavidC
sumber
4

Mathematica, 118 byte

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

Ini menghasilkan Ulam spiral dalam bentuk linier dengan mencatat bahwa posisi setiap angka selanjutnya dapat diakumulasikan sebagai

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

yaitu mulai dari pusat, lalu gerakkan 1 ke kanan, 1 ke atas, 2 ke kiri, 2 ke bawah, 3 ke kanan, 3 ke atas, ...

Keluaran:

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

sumber
1

Javascript, 516 363 304 276 243 240 Bytes

Solusi saya tidak membuat matriks padat dengan Spiral, melainkan mengembalikan indeks yang sesuai dengan angka yang diberikan dalam Matriks Ulam dari urutan yang diberikan. Jadi iterasi melalui angka antara 2 dan M * M dan menciptakan array bilangan prima dengan idx yang diberikan oleh 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);

Bentuk yang diperkecil seperti ini:

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

Untuk input 15 outputnya adalah:

,,,,,,,,,,,,,,,, 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
sumber
Itu adalah sedikit kompresi. Bisakah Anda menjelaskan kode asli dan perubahan Anda?
Addison Crump
Saya menghapus beberapa tanda kurung yang tidak berguna. Dan menyadari bahwa uI () memiliki 4 kondisi dengan blok yang sama. Masing-masing dengan 3 baris yang menghasilkan Baris dan Kolom untuk segmen saat ini (lihat docblock utama) jadi saya mengganti 4 blok dengan baris ll & llt dan baris kembali memutuskan apakah llt adalah baris atau kolom. S & 2 berlaku untuk s dalam (3,2) (segmen atas & kiri); s <3, untuk s dalam (1,2) kanan & atas. S & 1, untuk s dalam (1,3) akan menentukan apakah nilai dalam ll & llt adalah baris & col atau col & baris dan M (urutan spiral) × baris + col mencegah indeks yang tumpang tindih (seperti matriks rektifikasi tetapi dengan idx linier yang salah, kebenarannya akan butuh ll-1
juanmf
Dalam loop utama (run ()) hanya jika i adalah prima (yang fn dikurangi karena tidak perlu untuk menguji <2 atau% 1) ia meminta indeks i (ll, llt) dalam spiral, yang kemudian diperbaiki. Kemudian cukup cetak array hasil.
juanmf
Ada 3 matriks yang secara konseptual penting. Inner, curret & M. Berguna untuk menghitung baris & col absolut. Mengurangkan bagian dalam ke n membuat kita dengan int relatif dalam arus (yang jatuh n) putaran spiral. Dan perbedaan antara urutan M dan arus dimainkan sebagai offset untuk baris dan col pada putaran saat ini untuk mendapatkan yang absolut.
juanmf
364 -> 240 dengan menulis logika fn sebaris dan menghapus tes yang tidak digunakan.
juanmf