Attenzione al tornado della matrice!


27

Il tornado a matrice è proprio come qualsiasi altro tornado: consiste di cose che ruotano attorno a un centro. In questo caso, elementi della matrice anziché aria.

Ecco un esempio di tornado a matrice:

Matrix tornado in azione

Innanzitutto iniziamo sezionando la matrice in anelli quadrati, ogni sezione è composta da elementi che sono più lontani dal bordo alla stessa distanza. Queste sezioni verranno ruotate in senso orario attorno al centro. Nei tornado reali, la gravità aumenta verso il centro, così come il passo di rotazione in un tornado di matrice: la sezione più esterna (quella rossa) viene ruotata di 1 gradino, quella successiva (quella gialla) viene ruotata di 2, e così su. Una fase di rotazione è una rotazione di 90 ° attorno al centro.

Compito:

Il tuo compito, se lo accetti, è quello di scrivere una funzione o un programma che accetta come input una matrice quadrata, applica l'effetto tornado ad essa e quindi emette la matrice risultante.

Ingresso:

L'input dovrebbe essere una matrice quadrata di ordine in ncui n >= 1. Non si deve supporre che gli elementi della matrice possano essere qualsiasi cosa.

Produzione:

Una matrice quadrata dello stesso ordine che sarebbe il risultato dell'applicazione dell'effetto tronado alla matrice di input.

Esempi:

Una matrice di ordine n = 1:

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

Una matrice di ordine n = 2:

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

Una matrice di ordine 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]]

Penso che tu voglia chiarire che le rotazioni sono rotazioni di 90 °.
Erik the Outgolfer

Inoltre, hai preso questa sfida da qualche altra parte? In tal caso, è necessario fornire l'attribuzione.
Erik the Outgolfer,

1
@EriktheOutgolfer 1) L'ho chiarito. 2) Questa sfida è mia.
Ibrahim Mahrir,

4
@Giuseppe Dipende dall'emisfero in cui ti trovi;)
Jo King

12
Prima di tutto vorrei dire che penso sia una bella sfida: bel lavoro! Ma vorrei anche chiarire questo punto perché penso che la tua scelta di dire che potrebbe essere qualsiasi tipo di dati lasci la tua sfida in un punto imbarazzante. Allo stesso modo con la tua affermazione sull'input come un elenco di elenchi, hai limitato le lingue che possono risolvere questo problema senza fare un po 'di lavoro. Penso che la sfida sia migliore se questi requisiti sono rilassati. Spero che continuerai a pubblicare belle sfide come questa! :)
FryAmTheEggman

Risposte:


5

Python 3 , 100 byte

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

Provalo online!


8
Python classico, che cade a[1:-1,1:-1]=f(a[1:-1,1:-1])come se fosse la cosa più normale al mondo ottenere direttamente e impostare l'intero interno di un array bidimensionale
ETHproductions

1
@ETHproductions Per essere onesti, parte di ciò è la sintassi ereditata danumpy
Jo King

1
numpy.rot90(a,1,(1,0))è più corto di 3 byte e dovrebbe funzionare anche.
Graipher

1
Qual è il punto del collegamento TIO senza casi di test? ..: S Eccolo con (lasciato cadere lo spazio if len(a):a=...per -1 byte).
Kevin Cruijssen,

5

Carbone , 44 byte

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

Provalo online! Il collegamento è alla versione dettagliata del codice. Funziona solo sui quadrati dei personaggi perché l'I / O predefinito di Charcoal non rende giustizia alle normali matrici. Spiegazione:

≔EθSθ

Leggi la piazza del personaggio.

Wθ«

Ripeti finché non è vuoto.

≔Eθ⮌⭆觧θνλθ

Ruotalo.

θM¹⁻¹Lθ

Stampalo, ma sposta il cursore su un quadrato in diagonale dall'angolo originale.

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

Taglia l'esterno dall'array.


5

Gelatina , 27 byte

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

Provalo online!

Penso che questo potrebbe essere molto più breve.

           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
Probabilmente puoi semplicemente inserire µGil piè di pagina e affermare che la tua richiesta è 25.
Mr. Xcoder

5

Perl 6 , 78 73 72 byte

Grazie a nwellnhof per -5 byte!

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

Provalo online!

Blocco di codice ricorsivo che accetta un array 2D appiattito e restituisce un array appiattito in modo simile.

Spiegazione:

$!={      # 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
}

È possibile utilizzare @a[*;*]invece di map |*,@aappiattire l'array. (Sarebbe bello se ci fosse un modo di lavorare con array non appiattiti e sottoscrizioni multidimensionali, ma non riesco a pensarne uno.)
nwellnhof

Ma @a[1..*-2;1..@a-2].=$!funziona.
nwellnhof,

5

Ottava , 86 81 byte

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

Provalo online!

Sono consapevole che le funzioni anonime ricorsive non sono il metodo più breve per fare le cose in Octave, ma sono di gran lunga il metodo più divertente . Questa è la funzione anonima più breve che potrei inventare, ma mi piacerebbe essere superato.

Spiegazione

La funzione ricorsiva è definita in base a questa risposta da ceilingcat. q=f(f=@(g)@(M) ... g(g)(M) ...è la struttura di base di tale funzione anonima, con g(g)(M)la chiamata ricorsiva. Dal momento che questo sarebbe ricorsivamente all'infinito, ci avvolgiamo la chiamata ricorsiva in un array di celle condizionale: {@()g(g)(M),M}{condition}(). La funzione anonima con un elenco di argomenti vuoto ritarda la valutazione dopo che è stata selezionata la condizione (anche se in seguito, vediamo che è possibile utilizzare tale elenco di argomenti per definire z). Finora è stata solo una contabilità di base.

Ora per il lavoro effettivo. Vogliamo che la funzione ritorni rot90(P,-1)con P una matrice sulla quale g(g)è stata chiamata in modo ricorsivo sulla parte centrale di M. Iniziamo impostando z=2:end-1quale possiamo nascondere nell'indicizzazione di M. In questo modo, M(z,z)seleziona la parte centrale della matrice che deve essere dilaniato ulteriormente da una chiamata ricorsiva. La ,3parte assicura che le rotazioni siano in senso orario. Se vivi nell'emisfero meridionale, puoi rimuovere questo bit per -2 byte.

Quindi facciamo M(z,z)=g(g)M(z,z). Tuttavia, il valore del risultato di questa operazione è solo la parte centrale modificata anziché l'intera Pmatrice. Quindi, facciamo {M(z,z)=g(g)M(z,z),M}{2}che è fondamentalmente rubato da questo risposta da Stewie Griffin.

Infine, conditionè solo che la ricorsione si interrompe quando l'input è vuoto.


+1 per l'emisfero australe
plafoniera

Non ho ancora cercato di avvolgere la mia testa attorno alla ricorsione in funzioni anonime, quindi non ci proverò, ma sono curioso di vedere se la ricorsione è più breve dei cicli in questo .
Stewie Griffin,

@StewieGriffin Vedrò cosa posso fare :)
Sanchises

@StewieGriffin A proposito, ti invitiamo a pubblicare una versione basata su loop per questa sfida in Octave. Mi chiedo davvero se riesci a battere l'approccio ricorsivo.
Sanchises,

4

R , 87 byte

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}

Provalo online!



È permesso? L'immagine mostra una freccia in senso orario e la descrizione che segue indica la rotazione in senso orario ...
digEmAll

Devo aver letto la domanda dieci volte e non ho mai notato che afferma in senso orario (da qui il mio commento). Ahimè.
Giuseppe,

Eheh, parlamene ... Sono il re dei messaggi
male

1
Sfortunatamente la matrice 1x1 non funzionerà (perché seq(0.5)restituisce 1 invece del vettore vuoto)
digEmAll

4

MATL , 25 24 23 22

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

Provalo online!

L'indicizzazione in MATL non è mai facile, ma con un po 'di golf batte effettivamente la migliore risposta Jelly attuale ...

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. 

* Per una n x nmatrice, questo programma esegue niterazioni, mentre in realtà hai solo bisogno di n/2rotazioni. Tuttavia, l'indicizzazione in MATL (AB) è sufficientemente flessibile che l'indicizzazione di intervalli impossibili è solo una no-op. In questo modo, non è necessario sprecare byte per ottenere il numero di iterazioni giusto.



3

K (ngn / k) , 41 39 38 byte

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

Provalo online!

{ } funzione con argomento x

#xlunghezza di x- l'altezza della matrice

2##x due copie - altezza e larghezza (si presume siano uguali)

s:assegnare a sper "forma"

!stutti gli indici di una matrice di forma s, ad esempio, !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)

Questa è una matrice a 2 righe (elenco di elenchi) e le sue colonne corrispondono agli indici in una matrice 5x5.

&/ minimo sulle due file:

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:assegnare a i, reverse ( |) e take minima ( &) coni

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

Questi sono i numeri di squilli appiattiti di una matrice 5x5:

4!1+ aggiungi 1 e prendi i resti modulo 4

(+|:)è una funzione che ruota invertendo ( |- abbiamo bisogno del :per forzarlo ad essere monadico) e poi trasponendo ( +- poiché non è il verbo più giusto nel "treno", non abbiamo bisogno di a :)

4(+|:)\xapplicarlo 4 volte x, preservando risultati intermedi

,/' appiattire ciascuno

+ trasporre

( )@' indicizza ciascun valore a sinistra con ciascun valore a destra

s# rimodellare a s


2
Sarò felice di vedere la spiegazione del tuo codice
Galen Ivanov,

1
@GalenIvanov Certo. Non credo di poter golf ulteriormente, quindi potrei anche provare a spiegarlo.
ngn,

Grazie! Le tue soluzioni mi fanno venire voglia di iniziare a imparare k (o anche ngn / k :))
Galen Ivanov

@GalenIvanov Conoscendo J (e APL?), Ci sei già a metà strada. K è più piccolo e più semplice, quindi consiglio vivamente di impararlo e, naturalmente, sono felice di parlarne in qualsiasi momento nel frutteto . ngn / k è solo un sottoinsieme della cosa reale, ma ho l'obiettivo di renderlo veloce e pratico.
ngn,

Sì, penso che ci proverò.
Galen Ivanov,

3

JavaScript (ES6), 99 byte

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

Provalo online!

Come?

W

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

tx,yW=5m=2

(2222221112210122111222222)

k=m(x,y)

tx,yk

mentre gli altri rimangono invariati.

Ciò equivale a dire che una cella non viene ruotata se abbiamo:

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

qual è il test utilizzato nel codice:

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

Gelatina , 24 byte

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

Provalo online!

Penso che questo potrebbe essere molto più breve.

- Lynn


Mi chiedevo una soluzione come questa! Mi ḷ""sembra magico ^^ ti interessa aggiungere una spiegazione?
Lynn,

@Lynn L'ultima cosa che mi aspettavo era di sentire che ḷ""è magico. È solo ḷ"con un extra "... oh, c'è una leggera possibilità che ḷ"sia anche qualcosa che ho "inventato" che non è stato usato così tanto dal momento che spesso può essere sostituito con un singolo atomo (non in questo caso, come il anche l'input può contenere 0).
Erik the Outgolfer

2

Haskell , 108 byte

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

Provalo online!

Ho usato la trasposizione di Laikoni e l'ho modificata un po ', per ruotare una matrice di 90 °:

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

Spiegazione

r ruota una matrice di 90 °.

(!) è una funzione di livello superiore: "applica al centro". g![1,2,3,4,5]lo è [1] ++ g[2,3,4] ++ [5].

f è la funzione tornado: i casi base sono di dimensione 1 e 2 (in qualche modo 0 non funziona).

L'ultima riga è dove avviene la magia: applichiamo r.r.r.(f!).rsulle file centrali di xe quindi ruotiamo il risultato. Chiamiamo le righe di mezzo M . Vogliamo ricorrere sulle colonne centrali di M , e per arrivare a quelle, possiamo ruotare M e quindi usare (f!). Quindi usiamo r.r.rper ruotare di nuovo M nel suo orientamento originale.


2

Java 10, 198 192 byte

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 byte grazie a @ceilingcat .

Provalo online.

Spiegazione:

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è sostanzialmente usato per indicare in quale anello ci troviamo. E poi ruoterà questo anello, incluso tutto ciò che contiene al suo interno una volta in senso orario durante ogni iterazione.

La sostituzione della matrice di input viene eseguita perché Java è pass-by-reference, quindi la semplice impostazione r=msignificherebbe che entrambe le matrici vengono modificate durante la copia dalle celle, causando risultati errati. Dobbiamo quindi creare una nuova Objectmatrice (nuovo riferimento) e invece copiare i valori in ogni cella uno per uno.


1

MATLAB, 93 byte

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

Sono sicuro che questo può essere giocato a golf ancora in qualche modo.

Spiegazione

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

C (gcc) , 128 118 115 byte

-15 byte da @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);}

Provalo online!


1

Haskell, 274 byte

wè la funzione principale, che ha il tipo [[a]] -> [[a]]che ti aspetteresti.

Sono sicuro che un golfista Haskell più esperto potrebbe migliorare.

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

Potresti voler dare un'occhiata ai nostri consigli per giocare a golf a Haskell, ad es. L' uso delle protezioni al posto dei condizionali farà risparmiare alcuni byte.
Laikoni,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.