Прайми спіралі Улама


17

Спіраль Улама - це справді захоплююча, але дивовижна тема математики. Як це детально працює, ви можете ознайомитись тут , але короткий підсумок можна пояснити так:

Я починаю з написання одного, потім записую два праворуч від нього. Над двома я пишу трійку, а ліворуч від цього пишу чотири. Я продовжую цю схему обертання навколо 1 (і будь-яких чисел між мною і 1) нескінченно (або поки не сказано зупинятися), утворюючи спіральний візерунок. (див. приклад нижче)

Мета

Створіть програму, яка приймає n (завжди буде непарне число більше нуля) як вхід, що співвідноситься з кількістю рядків, а потім виводить значення рядків прайметів за рядком спіралі Ulam. Форматування може бути будь-яким способом, але повинно бути зрозумілим для людини та очевидним.

Наприклад, з урахуванням вводу 3 ваша програма повинна вивести 5,3,2,7, оскільки 3 рядки видають таку спіраль:

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

Оскільки це кодовий гольф, відповідь з найменшими байтами виграє (як би неефективно)! Стандартні лазівки неприйнятні.


Чи дозволена кінцева кома? Або ще краще, простір розділений, наприклад, `` 5 3 2 7``
Том Карпентер

5
Поки воно читається по-людськи і зможе сказати мені проліски, не соромтеся.
Аддісон Кримп

Відповіді:


8

Pyth, 20 байт

f}TPTsuC+R=hZ_GtyQ]]

Спробуйте в Інтернеті: Демонстрація

Цей код генерує повністю спіраль Улама, з'єднує всі лінії та фільтри для праймерів.

Пояснення:

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

В основному це створює спіраль потрібного розміру (запитується від користувача), потім розташовує її так, щоб вона відображалася у правильному порядку рядків. Це зберігається в. Далі він відображає всі значення, які є простими.

Як ви сказали в будь-якому читаному форматі, я зберег байт і пішов на вихід за замовчуванням disp (), який є (у вашому тестовому випадку, n = 3):

 5
 3
 2
 7

Як додатковий бонус, це працює для будь-якого n> 0, включаючи парні числа. Наприклад, вихід для 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
Дуже хороша! Приємно знати цю spiralфункцію
Луїс Мендо

6

CJam, 42 33 байт

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

Спробуйте в Інтернеті

Остання версія включає суттєві вдосконалення, запропоновані @Martin.

Метод побудови спіралі полягає в тому, щоб на кожному кроці повернути матрицю, яку ми маємо на 90 градусів, і додати рядок з додатковими числами. Це повторюється (n / 2) * 4раз.

Значення в отриманій матриці потім фільтрують, щоб бути простими.

Пояснення:

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.

Можна 2/4*було замінити на нього 2*чи ви його спеціально залишили?
ETHproductions

@ETHproductions Це не рівнозначно, оскільки це ціле ділення. Наприклад, для введення 3 результат повинен бути 4. Власне, тепер, коли я думаю про це, я вважаю, що є байт, який потрібно зберегти. (2*має бути правильним.
Рето Кораді

5

Математика 223

Це відповідає коду Куби для спіралі Улама. Тому я надсилаю це як вікі спільноти. Я просто пограв у нього в гольф і вибрав праймери, перелічені рядки, в яких вони проживають.

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]

Приклад

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

Щоб покращити показ екрана:

 %// MatrixForm

матриця


4

Математика, 118 байт

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

Це створює спіраль Улама в лінійній формі, зазначаючи, що положення кожного наступного числа можна накопичити як

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

тобто почніть від центру, потім рухайтеся 1 вправо, 1 вгору, 2 вліво, 2 вниз, 3 вправо, 3 вгору, ...

Вихід:

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

1

Javascript, 516 363 304 276 243 240 байт

Моє рішення не створює щільної матриці зі спіраллю, натомість повертає індекс, що відповідає заданому номеру в матриці Улама заданого порядку. Таким чином, воно перебирається через числа між 2 і M * M і створює масив простих чисел з idx, заданим 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);

Мінімізований виглядає так:

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

Для входу 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


Це було зовсім трохи стиснення. Чи можете ви пояснити свій початковий код та зміни?
Аддісон Кримп

Я зняв кілька марних дужок. І зрозумів, що uI () має 4 умови з подібними блоками. Кожен з 3 рядків, які створили рядок і стовпчик для поточного сегмента (див. Основний docblock), тому я замінюю чотири 4 блоки на рядки ll & llt, і лінія повернення визначає, чи llt буде рядком або стовпцем. S & 2 справедливо для s в (3,2) (верхній та лівий сегменти); s <3, для s в (1,2) праворуч і вгорі. S & 1, для s в (1,3) визначить, чи є значення в ll & llt рядком & col або col & рядок, а M (порядок спіралі) × рядок + col запобігає перекриванню індексів (наприклад, випрямляюча матриця, але з неправильним лінійним idx, правильність буде потрібно ll-1
juanmf

У головному циклі (run ()) лише якщо i є простим (який fn було зменшено, як ніколи не потрібно тестувати на <2, ні% 1), він запитує індекс (ll, llt) у спіралі, який називає виправленим. Потім просто надрукуйте масив результатів.
juanmf

Існує 3 концептуально важливих матриці. Внутрішня, каре і М. Корисно для обчислення абсолютних рядків і колів. Субстратація внутрішнього до n залишає uss з відносним інтом у струмі (той, у який падає n) спіраль круглої форми. І відмінність порядку М та поточного набору грає як зміщення для рядків і колів у поточному раунді, щоб отримати абсолютні.
juanmf

364 -> 240, записавши fn логіку inline та видаливши невикористані тести.
juanmf
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.