Остерегайтесь матричного торнадо!


27

Матричный торнадо, как и любой другой торнадо, состоит из вещей, вращающихся вокруг центра. В этом случае элементы матрицы вместо воздуха.

Вот пример матричного торнадо:

Матричный торнадо в действии

Сначала мы разбиваем матрицу на квадратные кольца, каждая секция состоит из элементов, которые находятся дальше от границы на одинаковое расстояние. Эти секции будут вращаться по часовой стрелке вокруг центра. В реальных торнадо серьезность возрастает по направлению к центру, как и шаг вращения в матричном торнадо: крайняя часть (красная) поворачивается на 1 шаг, следующая (желтая) - на 2, и так на. Шаг вращения - это поворот на 90 ° вокруг центра.

Задача:

Ваша задача, если вы примете это, - написать функцию или программу, которая принимает в качестве входных данных квадратную матрицу, применять к ней эффект торнадо и затем выводить полученную матрицу.

Входные данные:

На входе должна быть квадратная матрица порядка nгде n >= 1. Не следует делать никаких предположений об элементах матрицы, они могут быть чем угодно.

Выход:

Квадратная матрица того же порядка, которая будет результатом применения эффекта тронадо к входной матрице.

Примеры:

Матрица заказа n = 1:

[['Hello']]               ===>    [['Hello']]

Матрица заказа n = 2:

[[1 , 2],                 ===>    [[5 , 1],
 [5 , 0]]                          [0 , 2]]

Матрица заказа n = 5:

[[A , B , C , D , E],             [[+ , 6 , 1 , F , A],
 [F , G , H , I , J],              [- , 9 , 8 , 7 , B],
 [1 , 2 , 3 , 4 , 5],     ===>     [/ , 4 , 3 , 2 , C],
 [6 , 7 , 8 , 9 , 0],              [* , I , H , G , D],
 [+ , - , / , * , %]]              [% , 0 , 5 , J , E]]

Я думаю, что вы хотите уточнить, что повороты - это повороты на 90 °.
Эрик Outgolfer

Кроме того, вы взяли этот вызов откуда-то еще? Если это так, вы должны предоставить атрибуцию.
Эрик Outgolfer

1
@EriktheOutgolfer 1) Я уточнил это. 2) Этот вызов мой.
Ибрагим Махрир

4
@Giuseppe Зависит от того, в каком полушарии вы находитесь;)
Джо Кинг,

12
Во-первых, я хотел бы сказать, что я думаю, что это хороший вызов: хорошая работа! Но я также хотел бы остановиться на этом вопросе, потому что я думаю, что ваш выбор, что это могут быть данные любого типа, оставляет вашу проблему в неловком положении. Точно так же, как ваше заявление о том, что вводом является список списков, вы ограничили языки, которые могут решить эту проблему, не выполняя каких-либо дополнительных работ. Я думаю, что проблема будет лучше, если эти требования будут смягчены. Я надеюсь, что вы продолжаете публиковать хорошие задания, как это! :)
FryAmTheEggman

Ответы:


5

Python 3 , 100 байт

import numpy
def f(a):
 if len(a): a=numpy.rot90(a,axes=(1,0));a[1:-1,1:-1]=f(a[1:-1,1:-1]);return a

Попробуйте онлайн!


8
Классический Python, просто выпадающий, a[1:-1,1:-1]=f(a[1:-1,1:-1])как будто это самая обычная вещь в мире, чтобы напрямую получить и установить все внутри двухмерного массива
ETHproductions

1
@ETHproductions Чтобы быть справедливым, часть этого является синтаксисом, унаследованным отnumpy
Джо Кинг

1
numpy.rot90(a,1,(1,0))короче на 3 байта и тоже должно работать.
Graipher

1
Какой смысл в TIO-ссылке без каких-либо тестов? ..: S Вот она с (отбросил пробел на if len(a):a=...-1 байт).
Кевин Круйссен

5

Древесный уголь , 44 байта

≔EθSθWθ«≔Eθ⮌⭆觧θνλθθM¹⁻¹Lθ≔E✂θ¹±¹¦¹✂κ¹±¹¦¹θ

Попробуйте онлайн! Ссылка на подробную версию кода. Работает только на символьных квадратах, потому что ввод-вывод по умолчанию в Charcoal не дает нормальных значений. Объяснение:

≔EθSθ

Прочитайте квадрат персонажа.

Wθ«

Цикл, пока он не пуст.

≔Eθ⮌⭆觧θνλθ

Поверните это.

θM¹⁻¹Lθ

Напечатайте его, но затем переместите курсор на один квадрат по диагонали от исходного угла.

≔E✂θ¹±¹¦¹✂κ¹±¹¦¹θ

Обрезать снаружи от массива.


5

Желе , 27 байт

J«þ`UṚ«Ɗ‘ịZU$LСŒĖḢŒHEƊƇṁµG

Попробуйте онлайн!

Я думаю, что это может быть намного короче.

           Input: n×n matrix A.
J          Get [1..n].
 «þ`       Table of min(x, y).
    UṚ«Ɗ   min with its 180° rotation.

Now we have a matrix like: 1 1 1 1 1
                           1 2 2 2 1
                           1 2 3 2 1
                           1 2 2 2 1
                           1 1 1 1 1

‘ị          Increment all, and use as indices into...
     LС    List of [A, f(A), f(f(A)), …, f^n(A)]
  ZU$       where f = rotate 90°

Now we have a 4D array (a 2D array of 2D arrays).
We wish to extract the [i,j]th element from the [i,j]th array.

ŒĖ     Multidimensional enumerate

This gives us: [[[1,1,1,1],X],
                [[1,1,1,2],Y],
                ...,
                [[n,n,n,n],Z]]

ḢŒHEƊƇ     Keep elements whose Ḣead (the index) split into equal halves (ŒH)
           has the halves Equal to one another. i.e. indices of form [i,j,i,j]
           (Also, the head is POPPED from each pair, so now only [X] [Y] etc remain.)

ṁµG        Shape this like the input and format it in a grid.

1
Вероятно, вы можете просто вставить µGнижний колонтитул и заявить, что ваша заявка составляет 25.
Мистер Xcoder

5

Perl 6 , 78 73 72 байта

Спасибо nwellnhof за -5 байтов!

$!={my@a;{(@a=[RZ] rotor @_: sqrt @_)[1..*-2;1..@a-2].=$!}if @_;@a[*;*]}

Попробуйте онлайн!

Блок рекурсивного кода, который принимает сплющенный 2D-массив и возвращает аналогично сплющенный массив.

Объяснение:

$!={      # Assign code block to pre-declared variable $!
    my@a; # Create local array variable a
   {
     (@a=[RZ]  # Transpose:
             rotor @_: sqrt @_;  # The input array converted to a square matrix
     )[1..*-2;1..@a-2].=$!  # And recursively call the function on the inside of the array
   }if @_;    # But only do all this if the input matrix is not empty
   @a[*;*]  # Return the flattened array
}

Вы можете использовать @a[*;*]вместоmap |*,@a чтобы сгладить массив. (Было бы неплохо, если бы был способ работать с необработанными массивами и многомерными подписками, но я не могу придумать ни одного.)
nwellnhof

Но @a[1..*-2;1..@a-2].=$!работает.
nwellnhof

5

Октава , 86 81 байт

f(f=@(g)@(M,v=length(M))rot90({@(){M(z,z)=g(g)(M(z=2:v-1,z)),M}{2},M}{1+~v}(),3))

Попробуйте онлайн!

Я знаю, что рекурсивные анонимные функции - не самый короткий метод для действий в Octave, но на сегодняшний день это самый забавный метод. Это самая короткая анонимная функция, которую я мог придумать, но я бы хотел быть вне игры.

объяснение

Рекурсивная функция определяется в соответствии с этим ответ от потолка. q=f(f=@(g)@(M) ... g(g)(M) ...является базовой структурой такой анонимной функции с g(g)(M)рекурсивным вызовом. Так как это будет рекурсией на неопределенное время , мы оборачиваем рекурсивный вызов в массиве условной ячейки: {@()g(g)(M),M}{condition}(). Анонимная функция с пустым списком аргументов задерживает оценку после выбора условия (хотя позже мы увидим, что мы можем использовать этот список аргументов для определения z). До сих пор это была только базовая бухгалтерия.

Теперь о фактической работе. Мы хотим, чтобы функция возвращала rot90(P,-1)с помощью P матрицу, для которой g(g)был рекурсивно вызван центральный элемент M. Мы начнем с установки, z=2:end-1которую мы можем скрыть в индексировании M. Таким образом, M(z,z)выбирается центральная часть матрицы, которая должна быть торнадо дальше рекурсивным вызовом. ,3Часть гарантирует , что повороты по часовой стрелке. Если вы живете в южном полушарии, вы можете удалить этот бит на -2 байта.

Затем мы делаем M(z,z)=g(g)M(z,z) . Однако результатом этой операции является только измененная центральная часть, а не вся Pматрица. Следовательно, мы делаем то, {M(z,z)=g(g)M(z,z),M}{2}что в основном украдено из этого Stewie Griffin.

Наконец, condition рекурсия останавливается только тогда, когда ввод пуст.


+1 для южного полушария
потолочная кошка

Я еще не пытался обернуть голову вокруг рекурсии в анонимных функциях, поэтому я не буду пытаться сделать это, но мне любопытно посмотреть, короче ли рекурсия в этом цикле .
Стьюи Гриффин

@StewieGriffin Я посмотрю, что я могу сделать :)
Sanchises

@StewieGriffin Кстати, пожалуйста, опубликуйте петлевую версию этой задачи в Octave. Мне действительно интересно, если вы можете победить рекурсивный подход.
Санчиз

4

R , 87 байт

function(m,n=nrow(m)){for(i in seq(l=n%/%2))m[j,j]=t(apply(m[j<-i:(n-i+1),j],2,rev));m}

Попробуйте онлайн!



Это разрешено? На рисунке показана стрелка по часовой стрелке, а в приведенном ниже описании показано вращение по часовой стрелке ...
digEmAll

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

Эхех, расскажи мне об этом ... Я король
неверного

1
К сожалению, матрица 1x1 не будет работать (потому что seq(0.5)возвращает 1 вместо пустого вектора)
digEmAll

4

MATL , 25 24 23 22

t"tX@Jyq-ht3$)3X!7Mt&(

Попробуйте онлайн!

Индексирование в MATL никогда не бывает легким, но с некоторыми играми в гольф это на самом деле превосходит текущий лучший ответ Jelly ...

t                       % Take input implicitly, duplicate.  
 "                      % Loop over the columns of the input*
   X@                   % Push iteration index, starting with 0. Indicates the start of the indexing range.
     Jyq-               % Push 1i-k+1 with k the iteration index. Indicates the end of the indexing range
         t              % Duplicate for 2-dimensional indexing.
  t       3$)           % Index into a copy of the matrix. In each loop, the indexing range gets smaller
             3X!        % Rotate by 270 degrees anti-clockwise
                7Mt&(   % Paste the result back into the original matrix. 

* Для n x nматрицы эта программа выполняет nитерации, в то время как вам действительно нужны только n/2вращения. Однако индексация в MATL (AB) достаточно гибкая, поэтому индексация невозможных диапазонов - просто запрет. Таким образом, нет необходимости тратить байты на правильное количество итераций.



3

K (нгн / к) , 41 39 38 байт

{s#(+,/'4(+|:)\x)@'4!1+i&|i:&/!s:2##x}

Попробуйте онлайн!

{ } функция с аргументом x

#xдлина x- высота матрицы

2##x две копии - высота и ширина (предполагается одинаковыми)

s:назначить sдля "формы"

!sвсе индексы матрицы с формой s, например , !5 5является

(0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3 4 4 4 4 4
 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4)

Это двухстрочная матрица (список списков), и ее столбцы соответствуют индексам в матрице 5х5.

&/ минимум по двум рядам:

0 0 0 0 0 0 1 1 1 1 0 1 2 2 2 0 1 2 3 3 0 1 2 3 4

i&|i:назначить i, повернуть вспять ( |) и взять минимумы ( &) сi

0 0 0 0 0 0 1 1 1 0 0 1 2 1 0 0 1 1 1 0 0 0 0 0 0

Это сплющенные кольцевые числа матрицы 5x5:

4!1+ добавить 1 и взять остатки по модулю 4

(+|:)это функция, которая вращается путем реверса ( |нам нужно, :чтобы она была монадической), а затем транспонировать ( +поскольку это не самый правый глагол в «поезде», нам не нужен: )

4(+|:)\x примените это 4 раза на x , сохраняя промежуточные результаты

,/' сплющить каждого

+ транспонирования

( )@' индексировать каждое значение слева с каждым значением справа

s# изменить к s


2
Я буду рад видеть объяснение вашего кода
Гален Иванов

1
@GalenIvanov Конечно. Я не думаю, что смогу играть в гольф дальше, поэтому я мог бы попытаться объяснить это.
СПП

Благодарность! Ваши решения заставляют меня хотеть начать изучать k (или даже ngn / k :))
Гален Иванов

@GalenIvanov Будучи знакомым с J (и APL?), Вы уже на полпути. K меньше и проще, поэтому я очень рекомендую изучить его, и, конечно, я рад поговорить об этом в Orchard в любое время. ngn / k - это лишь часть реальной вещи, но я стремлюсь сделать ее быстрой и практичной.
СПП

Да, я думаю, что собираюсь попробовать это.
Гален Иванов

3

JavaScript (ES6), 99 байт

f=(a,k=m=~-a.length/2)=>~k?f(a.map((r,y)=>r.map(v=>y-m>k|m-y>k|--x*x>k*k?v:a[m+x][y],x=m+1)),k-1):a

Попробуйте онлайн!

Как?

Дана квадратная матрица ширины Wмы определяем:

мзнак равноW-12TИкс,Yзнак равноМаксимум(|Y-м|,|Икс-м|)

Пример вывода TИкс,Y для матрицы 5х5 (Wзнак равно5, мзнак равно2):

(2222221112210122111222222)

Начнем с Кзнак равном и выполнить вращение всех клеток на 90 ° по часовой стрелке (Икс,Y) удовлетворяющих:

TИкс,YК

в то время как остальные остаются без изменений.

Это эквивалентно тому, что ячейка не поворачивается, если мы имеем:

(Y-м>К) ИЛИ (м-Y>К) ИЛИ (Икс2>К2) с Иксзнак равном-Икс

какой тест используется в коде:

a.map((r, y) =>
  r.map(v =>
    y - m > k | m - y > k | --x * x > k * k ?
      v
    :
      a[m + x][y],
    x = m + 1
  )
)

Тогда мы уменьшаем К и начать снова, пока Кзнак равно-1 или Кзнак равно-3/2 (в зависимости от соотношения W). В любом случае, это вызывает наше состояние остановки:

~k === 0

3

Желе , 24 байта

ṙ⁹ṙ€
ḊṖ$⁺€ßḷ""ç1$ç-ZUµḊ¡

Попробуйте онлайн!

Я думаю, что это может быть намного короче.

- Линн


Я задумался о таком решении! Это ḷ""выглядит волшебно для меня ^^ Не хотите добавить объяснение?
Линн

@Lynn Последнее, что я ожидал, было услышать, что ḷ""это волшебно. Это просто ḷ"с дополнительным "... о, есть небольшая вероятность того, ḷ"что я тоже "изобрел" что-то, что не использовалось так много, так как его часто можно заменить одним атомом (не в этом случае, как вход может содержать 0тоже).
Эрик Outgolfer

2

Haskell , 108 байт

e=[]:e
r=foldl(flip$zipWith(:))e
g!(h:t)=h:g(init t)++[last t]
f[x,y]=r[x,y]
f[x]=[x]
f x=r$(r.r.r.(f!).r)!x

Попробуйте онлайн!

Я использовал транспонирование Лайкони и немного изменил его, чтобы повернуть массив на 90 °:

  e=[]:e;foldr(zipWith(:))e.reverse
 e=[]:e;foldl(flip$zipWith(:))e

объяснение

r вращает массив на 90 °.

(!)является функцией более высокого уровня: «применить к центру». g![1,2,3,4,5]есть [1] ++ g[2,3,4] ++ [5].

f является функцией торнадо: базовые случаи имеют размер 1 и 2 (почему-то 0 не работает).

В последней строке происходит волшебство: мы применяем r.r.r.(f!).rсредние ряды xи затем поворачиваем результат. Давайте назовем эти средние строки M . Мы хотим рекурсию на средние колонны из М , и получить на них, мы можем вращать M , а затем использовать (f!). Затем мы используем r.r.rдля поворота М обратно в исходную ориентацию.


2

Java 10, 198 192 байта

m->{int d=m.length,b=0,i,j;var r=new Object[d][d];for(;b<=d/2;b++){for(i=b;i<d-b;i++)for(j=b;j<d-b;)r[j][d+~i]=m[i][j++];for(m=new Object[d][d],i=d*d;i-->0;)m[i/d][i%d]=r[i/d][i%d];}return r;}

-6 байт благодаря @ceilingcat .

Попробуйте онлайн.

Объяснение:

m->{                         // Method with Object-matrix as both parameter and return-type
  int d=m.length,            //  Dimensions of the matrix
      b=0,                   //  Boundaries-integer, starting at 0
      i,j;                   //  Index-integers
  var r=new Object[d][d];    //  Result-matrix of size `d` by `d`
  for(;b<=d/2;b++){          //  Loop `b` in the range [0, `d/2`]
    for(i=b;i<d-b;i++)       //   Inner loop `i` in the range [`b`, `d-b`)
      for(j=b;j<d-b;)        //    Inner loop `j` in the range [`b`, `d-b`)
        r[j][d+~i]=          //     Set the result-cell at {`j`, `d-i-1`} to:
          m[i][j++];         //      The cell at {`i`, `j`} of the input-matrix
    for(m=new Object[d][d],  //   Empty the input-matrix
        i=d*d;i-->0;)        //   Inner loop `i` in the range (`d*d`, 0]
      m[i/d][i%d]            //     Copy the cell at {`i/d`, `i%d`} from the result-matrix
        =r[i/d][i%d];}       //      to the replaced input-matrix
  return r;}                 //  Return the result-matrix as result

bв основном используется, чтобы указать, на каком кольце мы находимся. И затем он будет вращать это кольцо, включая все внутри него, один раз по часовой стрелке во время каждой итерации.

Замена матрицы ввода выполняется потому, что Java является передачей по ссылке, поэтому простая установка r=mбудет означать, что обе матрицы изменяются при копировании из ячеек, что приводит к неверным результатам. Поэтому нам нужно создать новую Object-матрицу (новую ссылку) и вместо этого скопировать значения в каждую ячейку.


1

MATLAB, 93 байта

function m=t(m),for i=0:nnz(m),m(1+i:end-i,1+i:end-i)=(rot90(m(1+i:end-i,1+i:end-i),3));end;end

Я уверен, что это может быть как-то еще в гольфе.

объяснение

function m=t(m),                                                                          end % Function definition
                for i=0:nnz(m),                                                       end;    % Loop from 0 to n^2 (too large a number but matlab indexing doesn't care)
                                                            m(1+i:end-i,1+i:end-i)            % Take the whole matrix to start, and then smaller matrices on each iteration
                                                      rot90(                      ,3)         % Rotate 90deg clockwise (anti-clockwise 3 times)
                               m(1+i:end-i,1+i:end-i)=                                        % Replace the old section of the matrix with the rotated one


1

Haskell, 274 байта

w является основной функцией, которая имеет тип [[a]] -> [[a]] который вы ожидаете.

Я уверен, что более опытный игрок в Haskell мог бы улучшить это.

w m|t m==1=m|0<1=let m'=p m in(\a b->[h a]++x(\(o,i)->[h o]++i++[f o])(zip(tail a)b)++[f a])m'(w(g m'))
p m|t m==1=m|0<1=z(:)(f m)(z(\l->(l++).(:[]))(r(x h(i m)):(p(g m))++[r(x f(i m))])(h m))
t[]=1
t[[_]]=1
t _=0
h=head
f=last
x=map
i=tail.init
g=x i.i
z=zipWith
r=reverse

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