Uważaj na tornado matrycy!

27

Tornado matrycowe jest jak każde inne tornado: składa się z rzeczy obracających się wokół środka. W tym przypadku elementy macierzy zamiast powietrza.

Oto przykład tornada matrycowego:

Tornado Matrix w akcji

Najpierw zaczynamy od podzielenia macierzy na kwadratowe pierścienie, każda sekcja składa się z elementów, które są dalej od granicy o tę samą odległość. Sekcje te zostaną obrócone zgodnie z ruchem wskazówek zegara wokół środka. W prawdziwych tornadach nasilenie zwiększa się w kierunku środka, podobnie jak krok rotacji w tornado matrycowym: najbardziej zewnętrzna sekcja (czerwona) jest obracana o 1 stopień, kolejna (żółta) jest obracana o 2, i tak na. Krok obrotu to obrót o 90 ° wokół środka.

Zadanie:

Twoim zadaniem, jeśli je zaakceptujesz, jest napisanie funkcji lub programu, który przyjmuje jako dane wejściowe macierz kwadratową, stosuje do niej efekt tornado, a następnie wypisuje wynikową macierz.

Wkład:

Dane wejściowe powinny być kwadratową macierzą rzędu ngdzie n >= 1. Nie należy zakładać, że elementy macierzy mogą być czymkolwiek.

Wydajność:

Matryca kwadratowa tego samego rzędu, która byłaby wynikiem zastosowania efektu tronado do matrycy wejściowej.

Przykłady:

Macierz porządku n = 1:

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

Macierz porządku n = 2:

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

Macierz porządku 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]]
ibrahim mahrir
źródło
Myślę, że chcesz wyjaśnić, że obroty są obrotami 90 °.
Erik the Outgolfer
Czy podjąłeś to wyzwanie gdzieś indziej? Jeśli tak, musisz podać atrybucję.
Erik the Outgolfer
1
@EriktheOutgolfer 1) Wyjaśniłem to. 2) To wyzwanie jest moje.
ibrahim mahrir
4
@Giuseppe Zależy, na której półkuli się znajdujesz;)
Jo King
12
Najpierw chciałbym powiedzieć, że myślę, że to dobre wyzwanie: dobra robota! Ale chciałbym również podnieść ten punkt, ponieważ myślę, że wybór, że może to być dowolny rodzaj danych, pozostawia wyzwanie w niezręcznym miejscu. Podobnie w przypadku oświadczenia o tym, że dane wejściowe są listami, ograniczyłeś języki, które mogą rozwiązać ten problem bez wykonywania pewnych czynności ogólnych. Myślę, że wyzwanie jest lepsze, jeśli wymagania te są złagodzone. Mam nadzieję, że nadal będziesz publikować fajne wyzwania! :)
FryAmTheEggman

Odpowiedzi:

5

Python 3 , 100 bajtów

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

Wypróbuj online!

Aneesh Durg
źródło
8
Klasyczny Python, po prostu spada, a[1:-1,1:-1]=f(a[1:-1,1:-1])jakby to była najbardziej normalna rzecz na świecie, aby bezpośrednio uzyskać i ustawić całe wnętrze dwuwymiarowej tablicy
ETHproductions
1
@ETHproductions Aby być uczciwym, częścią tego jest składnia odziedziczona ponumpy
Jo King
1
numpy.rot90(a,1,(1,0))jest krótszy o 3 bajty i powinien również działać.
Graipher
1
Jaki jest sens łącza TIO bez żadnych przypadków testowych? ..: S Tutaj jest z (upuścił miejsce na if len(a):a=...-1 bajt).
Kevin Cruijssen
5

Węgiel drzewny , 44 bajty

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

Wypróbuj online! Link jest do pełnej wersji kodu. Działa tylko na polach postaci, ponieważ domyślne we / wy Charcoala nie oddają normalnej tablicy tablic. Wyjaśnienie:

≔EθSθ

Przeczytaj kwadrat postaci.

Wθ«

Pętla, aż będzie pusta.

≔Eθ⮌⭆觧θνλθ

Obróć to.

θM¹⁻¹Lθ

Wydrukuj go, a następnie przesuń kursor o jeden kwadrat po przekątnej od oryginalnego rogu.

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

Przytnij zewnętrzną stronę z tablicy.

Neil
źródło
5

Galaretka , 27 bajtów

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

Wypróbuj online!

Myślę, że może to być znacznie krótsze.

           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.
Lynn
źródło
1
Prawdopodobnie możesz po prostu wstawić µGstopkę i twierdzić, że twoje zgłoszenie to 25.
Mr. Xcoder
5

Perl 6 , 78 73 72 bajtów

Dzięki nwellnhof za -5 bajtów!

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

Wypróbuj online!

Rekurencyjny blok kodu, który pobiera spłaszczoną tablicę 2D i zwraca podobnie spłaszczoną tablicę.

Wyjaśnienie:

$!={      # 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
}
Jo King
źródło
Możesz użyć @a[*;*]zamiast map |*,@aspłaszczać tablicę. (Byłoby miło, gdyby istniał sposób pracy z niepłaszczonymi tablicami i wielowymiarowymi indeksami dolnymi, ale nie mogę wymyślić żadnego z nich.)
nwellnhof
Ale @a[1..*-2;1..@a-2].=$!działa.
nwellnhof
5

Oktawa , 86 81 bajtów

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

Wypróbuj online!

Wiem, że rekurencyjne funkcje anonimowe nie są najkrótszą metodą do robienia rzeczy w Octave, ale zdecydowanie są najbardziej zabawną metodą. To najkrótsza anonimowa funkcja, jaką mogłem wymyślić, ale chciałbym być obezwładniony.

Wyjaśnienie

Funkcja rekurencyjna jest zdefiniowana zgodnie z tymi udzielonymi przez pułapkę kota. q=f(f=@(g)@(M) ... g(g)(M) ...jest podstawową strukturą takiej anonimowej funkcji z g(g)(M)wywołaniem rekurencyjnym. Ponieważ byłoby to przeszukanie w nieskończoność, mamy zawinąć wywołanie rekurencyjne w warunkowej macierzy komórkowej: {@()g(g)(M),M}{condition}(). Funkcja anonimowa z pustą listą argumentów opóźnia ocenę po wybraniu warunku (chociaż później widzimy, że możemy użyć tej listy argumentów do zdefiniowania z). Do tej pory była to tylko podstawowa księgowość.

Teraz właściwa praca. Chcemy, aby funkcja zwracała rot90(P,-1)z P macierz, na której g(g)rekurencyjnie wywołano środkową część M. Zaczynamy od ustawienia, z=2:end-1które możemy ukryć w indeksowaniu M. W ten sposób M(z,z)wybiera się centralną część macierzy, która musi zostać rozdartym przez rekurencyjne wezwanie. ,3Część zapewnia, że obroty są do ruchu wskazówek zegara. Jeśli mieszkasz na półkuli południowej, możesz usunąć ten bit na -2 bajty.

Następnie robimy M(z,z)=g(g)M(z,z). Jednak wartością wynikową tej operacji jest tylko zmodyfikowana część centralna, a nie cała Pmacierz. Stąd, mamy {M(z,z)=g(g)M(z,z),M}{2}, która jest w zasadzie skradzione z tej Odpowiedź Stewie Griffin.

Wreszcie, po conditionprostu rekursja kończy się, gdy dane wejściowe są puste.

Sanchises
źródło
+1 dla półkuli południowej
pułap cat
Nie próbowałem jeszcze owijać głowy w rekurencję za pomocą anonimowych funkcji, więc nie spróbuję, ale jestem ciekawy, czy rekurencja jest krótsza niż pętle w tym .
Stewie Griffin,
@StewieGriffin Zobaczę, co da się zrobić :)
Sanchises
@StewieGriffin Przy okazji, prosimy o opublikowanie wersji pętlowej tego wyzwania w Octave. Naprawdę zastanawiam się, czy można pokonać podejście rekurencyjne.
Sanchises
4

R , 87 bajtów

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}

Wypróbuj online!

digEmAll
źródło
Czy to jest dozwolone Obraz pokazuje strzałkę zgodnie z ruchem wskazówek zegara, a poniższy opis wskazuje obrót zgodnie z ruchem wskazówek zegara ...
digEmAll
Musiałem przeczytać pytanie dziesięć razy i nigdy nie zauważyłem, że brzmi ono zgodnie z ruchem wskazówek zegara (stąd mój komentarz). Niestety.
Giuseppe
Eheh, opowiedz mi o tym ... Jestem królem błędnie odczytanych postów: D
digEmAll
1
Niestety macierz 1x1 nie będzie działać (ponieważ seq(0.5)zwraca 1 zamiast pustego wektora)
digEmAll
4

MATL , 25 24 23 22

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

Wypróbuj online!

Indeksowanie w MATL nigdy nie jest łatwe, ale przy niektórych golfach faktycznie przewyższa obecną najlepszą odpowiedź na galaretki ...

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. 

* W przypadku n x nmatrycy program wykonuje niteracje, podczas gdy tak naprawdę potrzebujesz tylko n/2rotacji. Indeksowanie w MATL (AB) jest jednak na tyle elastyczne, że indeksowanie niemożliwych zakresów jest po prostu niemożliwe. W ten sposób nie trzeba marnować bajtów, aby uzyskać odpowiednią liczbę iteracji.

Sanchises
źródło
3

Python 2 , 98 bajtów

def f(a):
 if a:a=zip(*a[::-1]);b=zip(*a[1:-1]);b[-2:0:-1]=f(b[-2:0:-1]);a[1:-1]=zip(*b)
 return a

Wypróbuj online!

TFeld
źródło
3

K (ngn / k) , 41 39 38 bajtów

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

Wypróbuj online!

{ } funkcja z argumentem x

#xdługość x- wysokość matrycy

2##x dwie kopie - wysokość i szerokość (zakłada się, że są takie same)

s:przypisać do sdla „kształtu”

!swszystkie wskaźniki macierzy z kształtem s, np. !5 5jest

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

Jest to macierz 2-rzędowa (lista list), a jej kolumny odpowiadają indeksom w macierzy 5x5.

&/ minimum w dwóch rzędach:

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:przypisz do i, reverse ( |) i weź minima ( &) za pomocą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

Oto spłaszczone numery pierścieni matrycy 5x5:

4!1+ dodaj 1 i weź pozostałe modulo 4

(+|:)jest funkcją, która obraca się przez odwrócenie ( |- potrzebujemy, :aby zmusić ją do monadyczności), a następnie transpozycję ( +- ponieważ nie jest to najbardziej prawy czasownik w „pociągu”, nie potrzebujemy :)

4(+|:)\xnakładaj 4 razy x, zachowując wyniki pośrednie

,/' spłaszcz każdy

+ transponować

( )@' indeksuj każdą wartość po lewej stronie z każdą wartością po prawej stronie

s# zmienić kształt na s

ngn
źródło
2
Z przyjemnością zobaczę wyjaśnienie twojego kodu
Galen Iwanow
1
@GalenIvanov Sure. Nie sądzę, żebym mógł dalej grać w golfa, więc równie dobrze mogę spróbować to wyjaśnić.
ngn
Dzięki! Twoje rozwiązania sprawiają, że chcę zacząć uczyć się k (lub nawet ngn / k :))
Galen Iwanow
@GalenIvanov Znając J (i APL?), Jesteś już w połowie drogi. K jest mniejszy i prostszy, więc bardzo polecam jego naukę i oczywiście chętnie o tym porozmawiam w sadzie w dowolnym momencie. ngn / k jest tylko podzbiorem prawdziwej rzeczy, ale staram się, aby była szybka i praktyczna.
ngn
Tak, myślę, że spróbuję.
Galen Iwanow
3

JavaScript (ES6), 99 bajtów

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

Wypróbuj online!

W jaki sposób?

W

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

Przykładowe dane wyjściowe dla macierzy 5x5 ( , ):tx,yW=5m=2

(2222221112210122111222222)

Zaczynamy od wykonujemy obrót wszystkich komórek o 90 ° zgodnie z ruchem wskazówek zegara spełniając:k=m(x,y)

tx,yk

podczas gdy pozostałe pozostały niezmienione.

Jest to równoważne z stwierdzeniem, że komórka nie jest obracana, jeśli mamy:

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

który jest testem zastosowanym w kodzie:

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

Następnie zmniejszamy i rozpoczynamy od nowa, aż lub (w zależności od parzystości ). Tak czy inaczej, powoduje to nasz stan zatrzymania:k = - 1 K = - 3 / 2 Wkk=1k=3/2W

~k === 0
Arnauld
źródło
3

Galaretka , 24 bajty

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

Wypróbuj online!

Myślę, że może to być znacznie krótsze.

- Lynn

Erik the Outgolfer
źródło
Zastanawiałem się nad takim rozwiązaniem! To ḷ""wygląda dla mnie magicznie ^ ^ Chcesz dodać wyjaśnienie?
Lynn,
@ Lynn Ostatnią rzeczą, jakiej się spodziewałem, było usłyszenie tego, co ḷ""jest magiczne. Jest tylko ḷ"z dodatkową "… och, istnieje niewielka możliwość, że ḷ"jest to również coś, co „wymyśliłem”, które nie było tak często używane, ponieważ często można go zastąpić jednym atomem (nie w tym przypadku, ponieważ wejście może 0również zawierać ).
Erik the Outgolfer
2

Haskell , 108 bajtów

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

Wypróbuj online!

Kiedyś transpozycję Laikoni jest i to trochę zmodyfikowana i obrócić o 90 ° w tablicy:

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

Wyjaśnienie

r obraca tablicę o 90 °.

(!)jest funkcją wyższego poziomu: „zastosuj do środka”. g![1,2,3,4,5]jest [1] ++ g[2,3,4] ++ [5].

f jest funkcją tornada: przypadki podstawowe mają rozmiar 1 i 2 (jakoś 0 nie działa).

W ostatnim wierszu dzieje się magia: nakładamy r.r.r.(f!).rna środkowe rzędy, xa następnie obracamy wynik. Nazwijmy te środkowe rzędy M . Chcemy recurse na środkowych kolumnach z M , a dostać się do tych, możemy obracać M , a następnie użyć (f!). Następnie używamy, r.r.raby obrócić M z powrotem do jego pierwotnej orientacji.

Lynn
źródło
2

Java 10, 198 192 bajtów

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 bajtów dzięki @ceilingcat .

Wypróbuj online.

Wyjaśnienie:

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

bsłuży w zasadzie do wskazania, przy którym dzwonimy. I wtedy obróci ten pierścień, włączając wszystko w nim raz w prawo podczas każdej iteracji.

Wymiana macierzy wejściowej jest wykonywana, ponieważ Java jest przekazywana przez odniesienie, więc po prostu ustawienie r=moznaczałoby, że obie macierze zostałyby zmodyfikowane podczas kopiowania z komórek, powodując nieprawidłowe wyniki. Dlatego musimy utworzyć nową Objectmacierz (nowe odniesienie) i skopiować wartości w każdej komórce jeden po drugim.

Kevin Cruijssen
źródło
1

MATLAB, 93 bajty

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

Jestem pewien, że można w jakiś sposób zagrać w golfa.

Wyjaśnienie

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
Jacob Watson
źródło
1

C (gcc) , 128 118 115 bajtów

-15 bajtów od @ceilingcat

j,i;f(a,b,w,s)int*a,*b;{for(j=s;j<w-s;j++)for(i=s;i<w-s;)b[~i++-~j*w]=a[i*w+j];wmemcpy(a,b,w*w);++s<w&&f(a,b,w,s);}

Wypróbuj online!

Vazt
źródło
1

Haskell, 274 bajty

wto główna funkcja, której [[a]] -> [[a]]można się spodziewać.

Jestem pewien, że bardziej doświadczony golfista Haskell mógłby to poprawić.

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
AlexJ136
źródło
Warto zapoznać się z naszymi wskazówkami dotyczącymi gry w golfa w Haskell, np. Użycie osłon zamiast warunkowych pozwoli zaoszczędzić trochę bajtów.
Laikoni