Ulam'ın Spiralin Asalları


17

Ulam'ın spirali, matematikte gerçekten büyüleyici, ama şaşırtıcı bir konudur. Ayrıntılı olarak nasıl çalıştığını burada bulabilirsiniz , ancak kısa bir özet şu şekilde açıklanabilir:

Bir tane yazarak başlıyorum, sonra sağına iki tane yazıyorum. İkisinin üzerine üç tane yazıyorum ve soluna dört tane yazıyorum. Sarmal bir desen oluşturarak, sonsuz bir şekilde (ya da durması söylenene kadar) 1 (ve ben ve 1 arasında herhangi bir sayı) daire çizmeye devam ediyorum. (aşağıdaki örneğe bakın)

Amaç

Satır sayısı ile ilişkili bir girdi olarak n (her zaman sıfırdan büyük tek bir sayı olacaktır) kabul eden bir program yapın , ardından primerlerin değerlerini Ulam spiralinin satır satır satırlarını yazdırın. Biçimlendirme herhangi bir moda olabilir ama gereken insan okunabilir ve aşikardır.

Örneğin, giriş 3 verildiğinde, programınız çıktı vermelidir 5,3,2,7, çünkü 3 satır aşağıdaki spirali üretir:

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

Bu bir kod golf olduğundan, en az bayt ile cevap kazanır (ne kadar verimsiz olursa olsun)! Standart boşluklar kabul edilemez.


Sonunda virgül var mı? Veya daha iyisi, boşluk ayrılmış, örneğin `` 5 3 2 7 ''
Tom Carpenter

5
İnsan tarafından okunabilir olduğu ve asalları söyleyebildiği sürece, çekinmeyin.
Addison Crump

Yanıtlar:


8

Pyth, 20 bayt

f}TPTsuC+R=hZ_GtyQ]]

Çevrimiçi deneyin: Gösteri

Bu kod, tam Ulam spiralini üretir, primerler için tüm hatları ve filtreleri bağlar.

Açıklama:

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

Temel olarak bu, gerekli boyutta (kullanıcıdan talep edilen) bir spiral oluşturur, daha sonra doğru satır düzeninde görünecek şekilde düzenler. Bu bir. Ardından, asal olan tüm değerleri görüntüler.

Herhangi bir okunabilir formatı söylediğiniz gibi, bir bayt sakladım ve varsayılan disp () çıktısına gittim (test durumunuzda n = 3):

 5
 3
 2
 7

Ek bir bonus olarak, çift sayılar da dahil olmak üzere n> 0 için çalışır. Örneğin, n = 10 için çıktı:

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
Çok hoş! Bu spiralişlevi bilmek güzel
Luis Mendo

6

CJam, 42 33 bayt

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

Çevrimiçi deneyin

En son sürüm @Martin tarafından önerilen önemli iyileştirmeleri içerir.

Spiralin yapım yöntemi, her adımda şimdiye kadar sahip olduğumuz matrisi 90 derece döndürmek ve ek sayılar içeren bir satır eklemektir. Bu tekrarlanır (n / 2) * 4.

Elde edilen matristeki değerler daha sonra primer oldukları için filtrelenir.

Açıklama:

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.

Could 2/4*ile değiştirilir 2*veya bilerek böyle bırakmış?
ETHproductions

@ETHproductions Bu bir tamsayı bölümü olduğu için eşdeğer değildir. Örneğin, giriş 3 için sonucun 4 olması gerekir. Aslında, şimdi düşündüğüme göre, kaydedilecek bir bayt olduğuna inanıyorum. (2*doğru olmalıdır.
Reto Koradi

5

Mathematica 223

Bu , Kuba'nın bir Ulam spirali kodunu uygun hale getirir. Bu yüzden bunu topluluk wiki'si olarak gönderiyorum. Ben sadece golf ve ikamet ettikleri satır tarafından listelenen asalları seçti.

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]

Misal

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

Ekranı iyileştirmek için:

 %// MatrixForm

matris


4

Mathematica, 118 bayt

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

Bu, takip eden her sayının konumunun şu şekilde toplanabileceğini belirterek Ulam spiralini lineer formda üretir.

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

yani merkezden başlayın, sonra 1 sağa, 1 yukarı, 2 sola, 2 aşağı, 3 sağa, 3 yukarı hareket ...

Çıktı:

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

1

JavaScript, 516 363 304 276 243 240 bayt

Benim çözümüm Spiral ile yoğun bir matris oluşturmaz, bunun yerine verilen siparişin Ulam Matrisinde verilen sayıya karşılık gelen dizini döndürür. Böylece 2 ve M * M arasındaki sayılar arasında yinelenir ve fn ulamIdx tarafından verilen idx ile bir dizi asal sayı oluşturur

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

Minimize edilmiş şuna benzer:

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

Giriş 15 için çıkış:

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


Bu biraz sıkıştırılmıştı. Orijinal kodunuzu ve değişikliklerinizi açıklayabilir misiniz?
Addison Crump

Bazı işe yaramaz parantezleri kaldırdım. Ve uI () 'nin benzer bloklarla 4 koşullu olduğunu fark etti. Geçerli segment için Satır ve Sütun oluşturulan 3 satır her (ana docblock bakın) böylece ll ll ll satır 4 blok yerine ve dönüş hattı llt satır veya sütun olup olmadığına karar verir. S & 2 (3,2) (üst ve sol segmentler) içindeki s için geçerlidir; s <3, (1,2) sağ ve üst s için. (1,3) 'deki s & 1, ll & llt içindeki değerlerin satır ve sütun veya sütun ve satır olup olmadığını belirleyecek ve M (spiral sıralaması) × satır + sütun çakışan indeksleri önleyecektir (düzeltme matrisi gibi ama yanlış doğrusal idx ile, doğruluk ll-1 gerek
juanmf

Ana döngüde (run ()) sadece i asal ise (hangi fn, <2 veya% 1 için test edilmesine gerek olmadığı için azaltıldı), spirallerin içinde rektifeler olan i indeksini (ll, llt) ister. Sonra sonuç dizisini yazdırın.
juanmf

Kavramsal olarak önemli 3 matris vardır. İç, perde ve M. Mutlak satır ve sütun hesaplamak için kullanışlıdır. N'den iç kısmın çıkarılması, bizi akımda (n'nin düştüğü) göreli bir int ile spiral yuvarlak bırakır. M'nin ve akımın sırası arasındaki fark, mutlak olanları elde etmek için mevcut turda satır ve col için ofset olarak oynar.
juanmf

364 -> 240 fn mantığı satır içi yazarak ve kullanılmayan testleri kaldırarak.
juanmf
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.