Vorsicht vor dem Matrix-Tornado!


27

Der Matrix-Tornado ist wie jeder andere Tornado: Er besteht aus Dingen, die sich um ein Zentrum drehen. In diesem Fall Elemente der Matrix anstelle von Luft.

Hier ist ein Beispiel für einen Matrix-Tornado:

Matrix Tornado in Aktion

Zunächst unterteilen wir die Matrix in quadratische Ringe, wobei jeder Abschnitt aus Elementen besteht, die um denselben Abstand vom Rand entfernt sind. Diese Abschnitte werden im Uhrzeigersinn um die Mitte gedreht. Bei echten Tornados nimmt der Schweregrad zur Mitte hin zu, ebenso wie der Rotationsschritt bei einem Matrix-Tornado: Der äußerste Abschnitt (der rote) wird um 1 Schritt gedreht, der nächste (der gelbe) um 2, und so weiter auf. Ein Rotationsschritt ist eine 90 ° -Drehung um das Zentrum.

Aufgabe:

Ihre Aufgabe ist es, eine Funktion oder ein Programm zu schreiben, das eine quadratische Matrix als Eingabe verwendet, den Tornado-Effekt darauf anzuwenden und dann die resultierende Matrix auszugeben.

Eingang:

Die Eingabe sollte eine quadratische Matrix der Reihenfolge sein, nin der n >= 1. Es ist keine Annahme über die Elemente der Matrix zu treffen, sie könnten alles sein.

Ausgabe:

Eine quadratische Matrix derselben Ordnung, die das Ergebnis der Anwendung des Tronado-Effekts auf die Eingangsmatrix wäre.

Beispiele:

Eine Matrix der Ordnung n = 1:

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

Eine Matrix der Ordnung n = 2:

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

Eine Matrix der Ordnung 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]]

Ich denke, dass Sie klarstellen möchten, dass die Drehungen 90 ° -Drehungen sind.
Erik der Outgolfer

Haben Sie diese Herausforderung auch von woanders angenommen? In diesem Fall müssen Sie eine Namensnennung vornehmen.
Erik der Outgolfer

1
@EriktheOutgolfer 1) Ich habe das geklärt. 2) Diese Herausforderung ist meine.
Ibrahim Mahrir

4
@ Giuseppe Hängt davon ab, in welcher Hemisphäre Sie sich befinden;)
Jo King

12
Zunächst möchte ich sagen, dass dies eine gute Herausforderung ist: gute Arbeit! Aber ich möchte diesen Punkt auch ansprechen , da Ihre Entscheidung, zu sagen, dass es sich um jede Art von Daten handeln könnte, Ihre Herausforderung an einer schwierigen Stelle hinterlässt. In ähnlicher Weise haben Sie mit Ihrer Aussage, dass die Eingabe eine Liste von Listen ist, die Sprachen eingeschränkt, die dieses Problem lösen können, ohne dass Overhead-Arbeiten anfallen. Ich denke, die Herausforderung ist besser, wenn diese Anforderungen gelockert werden. Ich hoffe du postest weiterhin so nette Herausforderungen! :)
FryAmTheEggman

Antworten:


5

Python 3 , 100 Bytes

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

Probieren Sie es online!


8
Klassisches Python, einfach fallen lassen, a[1:-1,1:-1]=f(a[1:-1,1:-1])als wäre es die normalste Sache der Welt, das gesamte Innere eines zweidimensionalen Arrays
direkt abzurufen

1
@ETHproductions fair zu sein, ein Teil davon wird Syntax geerbt vonnumpy
Jo König

1
numpy.rot90(a,1,(1,0))ist um 3 Bytes kürzer und sollte auch funktionieren.
Graipher

1
Was bringt der TIO-Link ohne Testfälle? ..: S Hier ist es mit (Leerzeichen um if len(a):a=...für -1 Byte).
Kevin Cruijssen

5

Kohle , 44 Bytes

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

Probieren Sie es online! Link ist eine ausführliche Version des Codes. Funktioniert nur auf Zeichenfeldern, da Charcoals Standard-E / A normalen Arrays nicht gerecht wird. Erläuterung:

≔EθSθ

Lesen Sie das Zeichenfeld.

Wθ«

Schleife, bis es leer ist.

≔Eθ⮌⭆觧θνλθ

Drehe es.

θM¹⁻¹Lθ

Drucken Sie es aus, und bewegen Sie den Cursor von der ursprünglichen Ecke aus auf ein Quadrat diagonal nach innen.

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

Schneiden Sie die Außenseite vom Array ab.


5

Gelee , 27 Bytes

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

Probieren Sie es online!

Ich denke, das könnte viel kürzer sein.

           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
Sie können wahrscheinlich einfach µGin die Fußzeile
schreiben

5

Perl 6 , 78 73 72 Bytes

Danke an nwellnhof für -5 Bytes!

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

Probieren Sie es online!

Rekursiver Codeblock, der ein abgeflachtes 2D-Array verwendet und ein ähnlich abgeflachtes Array zurückgibt.

Erläuterung:

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

Sie können @a[*;*]stattdessen verwenden map |*,@a, um das Array zu reduzieren. (Es wäre schön, wenn es eine Möglichkeit gäbe, mit nicht abgeflachten Arrays und mehrdimensionalen Subskripten zu arbeiten, aber mir fällt keine ein.)
nwellnhof

Funktioniert aber @a[1..*-2;1..@a-2].=$!.
Nwellnhof

5

Oktave , 86 81 Bytes

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

Probieren Sie es online!

Ich bin mir bewusst, dass rekursive anonyme Funktionen nicht die kürzeste Methode sind, um Dinge in Octave zu erledigen, aber sie sind bei weitem die unterhaltsamste Methode. Dies ist die kürzeste anonyme Funktion, die ich mir vorstellen konnte, aber ich würde gerne überrumpelt werden.

Erläuterung

Die rekursive Funktion wird nach diesen von ceilingcat beantwortet. q=f(f=@(g)@(M) ... g(g)(M) ...ist die Grundstruktur einer solchen anonymen Funktion mit g(g)(M)dem rekursiven Aufruf. Da diese auf unbestimmte Zeit Rekursion würde, wickeln wir den rekursiven Aufruf in einem bedingten Zellenfeld: {@()g(g)(M),M}{condition}(). Die anonyme Funktion mit leerer Argumentliste verzögert die Auswertung, nachdem die Bedingung ausgewählt wurde (obwohl wir später sehen, dass wir diese Argumentliste zum Definieren verwenden können z). Bisher war es nur eine einfache Buchhaltung.

Nun zur eigentlichen Arbeit. Wir möchten, dass die Funktion rot90(P,-1)mit P eine Matrix g(g)zurückgibt, die im zentralen Teil von M rekursiv aufgerufen wurde. Wir beginnen mit der Einstellung, z=2:end-1die wir in der Indizierung von M ausblenden können. Auf diese Weise M(z,z)wird der zentrale Teil der Matrix ausgewählt, der benötigt wird durch einen rekursiven Aufruf weiter aufgewühlt werden. Das ,3Teil stellt sicher, dass die Drehungen im Uhrzeigersinn sind. Wenn Sie auf der südlichen Hemisphäre leben, können Sie dieses Bit für -2 Bytes entfernen.

Wir machen es dann M(z,z)=g(g)M(z,z). Der Ergebniswert dieser Operation ist jedoch nur der modifizierte zentrale Teil und nicht die gesamte PMatrix. Daher tun wir das, {M(z,z)=g(g)M(z,z),M}{2}was Stewie Griffin aus dieser Grunde genommen gestohlen hat .

Schließlich conditionstoppt die Rekursion nur, wenn die Eingabe leer ist.


+1 für die südliche Hemisphäre
Ceilingcat

Ich habe noch nicht versucht, mich in anonymen Funktionen mit Rekursion zu beschäftigen, daher werde ich es nicht versuchen, aber ich bin gespannt, ob die Rekursion in dieser Funktion kürzer als die Schleifen ist .
Stewie Griffin

@ StewieGriffin Ich werde sehen, was ich tun kann :)
Sanchises

@StewieGriffin Übrigens, bitte fühlen Sie sich aufgefordert, eine auf einer Schleife basierende Version für diese Herausforderung in Octave zu veröffentlichen. Ich frage mich wirklich, ob Sie den rekursiven Ansatz schlagen können.
Sanchises

4

R 87 Bytes

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}

Probieren Sie es online!



Ist es erlaubt Das Bild zeigt einen Pfeil im Uhrzeigersinn und die Beschreibung darunter zeigt die Drehung im Uhrzeigersinn ...
digEmAll

Ich muss die Frage zehn Mal gelesen haben und habe nie bemerkt, dass sie im Uhrzeigersinn steht (daher mein Kommentar). Ach.
Giuseppe

Eheh, erzähl mir davon ... Ich bin der König der falsch
lesenden

1
Leider funktioniert die 1x1-Matrix nicht (da seq(0.5)statt eines leeren Vektors 1 zurückgegeben wird)
digEmAll

4

MATL , 25 24 23 22

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

Probieren Sie es online!

Das Indexieren in MATL ist nie einfach, aber mit etwas Golf schlägt es tatsächlich die aktuell beste Gelee-Antwort ...

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. 

* Für eine n x nMatrix führt dieses Programm nIterationen durch, während Sie wirklich nur n/2Rotationen benötigen . Die Indizierung in MATL (AB) ist jedoch so flexibel, dass die Indizierung unmöglicher Bereiche nur ein No-Op ist. Auf diese Weise müssen keine Bytes verschwendet werden, um die richtige Anzahl von Iterationen zu erhalten.



3

K (ngn / k) , 41 39 38 Bytes

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

Probieren Sie es online!

{ } Funktion mit Argument x

#x Länge von x - die Höhe der Matrix

2##x zwei Kopien - Höhe und Breite (als gleich vorausgesetzt)

s: zuweisen s für "Form"

!sAlle Indizes einer Matrix mit Form s, beispielsweise !5 5ist

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

Dies ist eine 2-zeilige Matrix (Liste von Listen) und ihre Spalten entsprechen den Indizes in einer 5x5-Matrix.

&/ Minimum über die beiden Reihen:

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:zuweisen i, umkehren ( |) und Minima nehmen ( &) miti

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

Dies sind die abgeflachten Ringnummern einer 5x5-Matrix:

4!1+ addiere 1 und nimm die restlichen modulo 4

(+|:)ist eine Funktion, die sich umkehrt ( |- wir müssen :sie zwingen, monadisch zu sein) und dann transponiert ( +- da es nicht das am weitesten rechts stehende Verb im "Zug" ist, brauchen wir kein :).

4(+|:)\xWenden Sie es 4-mal auf x, um Zwischenergebnisse zu erhalten

,/' jeweils abflachen

+ transponieren

( )@' Indizieren Sie jeden Wert auf der linken Seite mit jedem Wert auf der rechten Seite

s# umformen zu s


2
Ich freue mich, die Erklärung Ihres Codes zu sehen
Galen Ivanov

1
@GalenIvanov Sicher. Ich glaube nicht, dass ich weiter Golf spielen kann, also könnte ich genauso gut versuchen, es zu erklären.
ngn

Vielen Dank! Ihre Lösungen lassen mich anfangen zu lernen k (oder sogar ngn / k :))
Galen Ivanov

@GalenIvanov Da Sie mit J (und APL?) Vertraut sind, sind Sie schon auf halbem Weg. K ist kleiner und einfacher, daher würde ich es sehr empfehlen, es zu lernen, und ich freue mich natürlich, jederzeit darüber im Obstgarten zu plaudern . ngn / k ist nur eine Teilmenge der realen Sache, aber ich bemühe mich, es schnell und praktisch zu machen.
1.

Ja, ich denke, ich werde es versuchen.
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

Probieren Sie es online!

Wie?

W

m=W-12tx,y=max(|y-m|,|x-m|)

tx,yW=5m=2

(2222221112210122111222222)

Wir beginnen mit k=m und führen Sie eine Drehung aller Zellen um 90 ° im Uhrzeigersinn durch (x,y) befriedigend:

tx,yk

während die anderen unverändert bleiben.

Dies bedeutet, dass eine Zelle nicht gedreht wird, wenn Folgendes vorliegt:

(y-m>k) ODER (m-y>k) ODER (X2>k2) mit X=m-x

Welcher Test wird im Code verwendet:

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

Dann dekrementieren wir k und fange nochmal an, bis k=-1 oder k=-3/2 (abhängig von der Parität von W). In jedem Fall löst es unseren Haltezustand aus:

~k === 0

3

Gelee , 24 Bytes

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

Probieren Sie es online!

Ich denke, das könnte viel kürzer sein.

- Lynn


Ich habe mich über eine solche Lösung gewundert! Das ḷ""sieht für mich magisch aus ^^ Möchtest du eine Erklärung hinzufügen?
Lynn

@Lynn Das Letzte, was ich erwartet hatte, war zu hören, dass ḷ""es magisch ist. Es ist nur ḷ"mit einem Extra "... oh, es gibt eine kleine Möglichkeit, die ḷ"ich auch "erfunden" habe und die nicht so oft verwendet wurde, da sie oft durch ein einzelnes Atom ersetzt werden kann (in diesem Fall nicht als das Eingabe kann auch enthalten 0).
Erik der Outgolfer

2

Haskell , 108 Bytes

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

Probieren Sie es online!

Ich habe Laikonis Transponierte benutzt und ein wenig modifiziert, um ein Array um 90 ° zu drehen:

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

Erläuterung

r Dreht ein Array um 90 °.

(!)ist eine übergeordnete Funktion: „Auf Mitte anwenden“. g![1,2,3,4,5]ist [1] ++ g[2,3,4] ++ [5].

f ist die Tornado-Funktion: Die Basisfälle sind Größe 1 und 2 (irgendwie funktioniert 0 nicht).

In der letzten Zeile geschieht die Magie: Wir wenden r.r.r.(f!).rauf die mittleren Reihen von an xund drehen dann das Ergebnis. Nennen wir diese mittleren Reihen M . Wir wollen auf die mittleren Spalten von M zurückgreifen , und um an diese heranzukommen , können wir M drehen und dann verwenden (f!). Dann r.r.rdrehen wir M zurück in seine ursprüngliche Ausrichtung.


2

Java 10, 198 192 Bytes

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 Bytes dank @ceilingcat .

Probieren Sie es online aus.

Erläuterung:

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

bwird im Grunde genommen verwendet, um anzuzeigen, an welchem ​​Ring wir gerade sind. Und dann dreht es diesen Ring, einschließlich allem, was sich darin befindet, einmal im Uhrzeigersinn während jeder Iteration.

Das Ersetzen der Eingabematrix erfolgt, weil Java als Referenz übergeben wird. r=mWenn Sie also einfach festlegen, werden beim Kopieren aus Zellen beide Matrizen geändert, was zu falschen Ergebnissen führt. Wir müssen daher eine neue ObjectMatrix (neue Referenz) erstellen und stattdessen die Werte nacheinander in jede Zelle kopieren.


1

MATLAB, 93 Bytes

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

Ich bin sicher, das kann man noch irgendwie spielen.

Erläuterung

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 Bytes

wist die Hauptfunktion, die den Typ hat [[a]] -> [[a]], den Sie erwarten würden.

Ich bin sicher, dass ein erfahrener Haskell-Golfer dies verbessern könnte.

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

Vielleicht möchten Sie unsere Tipps zum Golfen in Haskell lesen, z. B. werden durch die Verwendung von Wachen anstelle von Bedingungen einige Bytes gespart.
Laikoni
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.