Простые числа спирали Улама


17

Спираль Улама - действительно захватывающая, но загадочная тема в математике. Как это работает в деталях, можно узнать здесь , но краткое резюме можно объяснить так:

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

Цель

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

Например, учитывая вход 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

МАТЛАБ, 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

Mathematica 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

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

Minified выглядит так:

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 строками, которые сгенерировали строку и столбец для текущего сегмента (см. Основной докблок), поэтому я заменяю эти 4 блока на 11 и 11 строк, а в ответной строке определяется, будет ли это строка или столбец. S & 2 верно для s в (3,2) (верхний и левый сегменты); s <3, для s в (1,2) справа и сверху. S & 1, для s в (1,3) будет определено, являются ли значения в ll & llt строкой и столбцом или столбцом и строкой, а M (спиральный порядок) × строка + столбец предотвращает перекрывающиеся индексы (как выпрямляющая матрица, но с неправильным линейным идентификатором, правильность будет нужно ll-1
'32

В основном цикле (run ()), только если i простое число (которое fn было уменьшено, поскольку никогда не нужно проверять на <2 или% 1), оно запрашивает индекс i (ll, llt) в спирали, которая выпрямляется. Затем просто распечатайте массив результатов.
июня

Есть 3 концептуально важных матрицы. Inner, curret & M. Полезно для расчета абсолютной строки и кол. Вычитание внутреннего к n оставляет нас с относительным int в текущем (тот, в котором n падает) спираль вокруг. И разница между M и текущим порядком играет смещение для строки и столбца в текущем раунде, чтобы получить абсолютные единицы.
2015 года

364 -> 240 путем написания встроенной логики fn и удаления неиспользуемых тестов.
августа
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.