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


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 °.
Ерік Аутгольфер

Також ви взяли цей виклик десь із іншого? Якщо так, ви повинні надати атрибуцію.
Ерік Аутгольфер

1
@EriktheOutgolfer 1) Я уточнив це. 2) Цей виклик мій.
ibrahim mahrir

4
@Giuseppe Залежить, на якій півкулі ви перебуваєте;)
Jo King

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
Jo King

1
numpy.rot90(a,1,(1,0))скорочується на 3 байти і також повинен працювати.
Грайфер

1
У чому сенс TIO-посилання без будь-яких тестових випадків? ..: S Ось це з (скинув пробіл на if len(a):a=...-1 байт).
Кевін Кройсейсен

5

Вугілля деревне , 44 байти

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

Спробуйте в Інтернеті! Посилання на багатослівну версію коду. Працює лише на квадрати символів, тому що введення / виведення за замовчуванням вугілля деревного вугілля не спрацьовує нормальні масиви. Пояснення:

≔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}який в основному вкрадений від цього відповіді по Стьюї Гріффін.

Нарешті, 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

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

Еге, розкажи мені про це ... Я король помилкових повідомлень: D
digEmВсі

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

К (нг / к) , 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)

Це 2-рядова матриця (список списків) і її стовпці відповідають індексам у матриці 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
@ ГаленІванов Впевнений. Я не думаю, що я більше можу це зробити в гольф, тому я б також спробував це пояснити.
ngn

Спасибі! Ваші рішення змушують мене почати вчитися k (або навіть ngn / k :))
Гален Іванов,

@GalenIvanov Знайомлячись з J (та APL?), Ти вже на півдорозі. K менший і простіший, тому я б дуже рекомендував вивчити його і, звичайно, я радий поговорити про це в Орчарді будь-коли. ngn / k - лише підмножина реальної речі, але я прагну зробити це швидким і практичним.
ngn

Так, я думаю, я спробую це спробувати.
Гален Іванов

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

m=W12tx,y=max(|ym|,|xm|)

tx,yW=5m=2

(2222221112210122111222222)

k=m(x,y)

tx,yk

а інші залишаються незмінними.

Це рівнозначно тому, що комірка не обертається, якщо у нас є:

(ym>k) OR (my>k) OR (X2>k2) with X=mx

який тест використовується в коді:

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

kk=1k=3/2W

~k === 0

3

Желе , 24 байти

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

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

Я думаю, це може бути набагато коротшим.

- Лінн


Я задумався про таке рішення! ḷ""Для мене це виглядає магічно ^^ турботою додати пояснення?
Лінн

@Lynn Останнє, що я очікував - це почути ḷ""це магічно. Це просто ḷ"з додатковим "... о, є невелика ймовірність, що ḷ"це теж те, що я "винайшов", що не використовувався так багато, оскільки його часто можна замінити одним атомом (не в цьому випадку, як Вхід може містити 0теж).
Ерік Аутгольфер

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]]який можна було б очікувати.

Я впевнений, що досвідчений гольфіст Хаскелл міг би покращити це.

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.