2D-Matrix drehen


30

Angenommen, ich habe die folgende (2D) Matrix:

[[1,  2,  3,  4 ],
 [5,  6,  7,  8 ],
 [9,  10, 11, 12],
 [13, 14, 15, 16]]

Drehen Sie die Matrix gegen den UhrzeigersinnR (nicht in 90-Grad-Schritten, sondern jeweils nur um eine Zahl).

1  2  3  4             2 3   4  8         3   4   8  12
5  6  7  8    -->      1 7  11 12   -->   2  11  10  16 
9  10 11 12            5 6  10 16         1   7   6  15 
13 14 15 16            9 13 14 15         5   9  13  14

Abgeschlossenes Beispiel:

Eingang:

2
[[1,  2,  3,  4 ],
 [5,  6,  7,  8 ],
 [9,  10, 11, 12],
 [13, 14, 15, 16]]

Ausgabe:

[[3,  4,  8, 12],
 [2, 11, 10, 16],
 [1,  7,  6, 15],
 [5,  9, 13, 14]]

(Seltsame Leerzeichen sollen die Zahlen in schönen Spalten ausrichten)

Der äußere "Ring" der Matrix dreht sich 2 gegen den Uhrzeigersinn und der innere rechte dreht sich 2 ebenfalls. In dieser Matrix gibt es nur zwei Ringe.

Ein Beispiel mit 1 "Ring":

2
[[1, 2],
 [3, 4],
 [5, 6]]

Sollte ausgeben:

[[4, 6],
 [2, 5],
 [1, 3]]

Ihre Herausforderung besteht darin, eine Matrix und eine Ganzzahl aufzunehmen Rund die übersetzte Version nach RRotationen auszugeben .

Die Drehung einer 4x5-Matrix wird durch die folgende Abbildung dargestellt: Bildbeschreibung hier eingeben

Einschränkungen:

  • 2 ≤ M, N ≤ 100, wobei M und N die Dimensionen der Matrix sind. Es ist garantiert, dass das Minimum von M und N gerade ist.
  • 1 ≤ R ≤ 80, wobei r die Anzahl der Umdrehungen ist.
  • Die Matrix enthält immer nur positive ganze Zahlen.
  • Werte sind nicht immer unterschiedlich.
  • Die Eingabe sollte immer als 2D-Array erfolgen (wenn Sie keine Laufzeiteingabe als 2D-Array verwenden können, müssen Sie nur einen anderen Weg finden, um Eingaben zu erhalten).

Ein weiterer Testfall mit nicht eindeutigen Werten:

1
[[1, 1],
 [2, 2],
 [3, 3]]

Ausgänge:

[[1, 2],
 [1, 3],
 [2, 3]]

Dies ist , so dass die kürzeste Antwort gewinnt!





4
@ceasedtoturncounterclockwis Ihr Name ist sehr ironisch für diese Herausforderung ...
HyperNeutrino

1
[[3, 4, 8, 12], [2, 11, 10, 16], [1, 7, 6, 16], [5, 9, 13, 14]]die 16 ist plötzlich dupliziert, denke ich sollte es sein [[3, 4, 8, 12], [2, 11, 10, 16], [1, 7, 6, 15], [5, 9, 13, 14]]:?
Christoph

Antworten:



5

Oktave, 210 Bytes

function M=F(M,R);f=@(z)[-z/2:-1 !eye(!!mod(z,2)) 1:z/2];t=angle(f([x y]=size(M))'+f(y)*i);B=!!M;B(2:x-1,2:y-1)=0;d=bwdist(B,'ch');[~,I]=sortrows([d(:) t(:)]);for k=0:max(d(:));M(h)=shift(M(h=I(d(I)==k)),R);end

Probieren Sie es auf Octave Online aus!

Ungolfed-Version:

function M=F(M,R)
    [x y]=size(M);
    f=@(z)[-z/2:-1 !eye(!!mod(z,2)) 1:z/2];
    t=angle(f(x)'+f(y)*i);
    B=!!M;
    B(2:x-1,2:y-1)=0;
    d=bwdist(B,'chessboard');
    [~,I]=sortrows([d(:) t(:)]);
    for k=0:max(d(:))
        M(h)=shift(M(h=I(d(I)==k)),R);
    end
end
R=2;
M=randi(10,4,7)
F(M,R)

Erläuterung:

f=@(z)[-z/2:-1 !eye(!!mod(z,2)) 1:z/2]; 

Eine Funktion, die eine Zahl erhält und einen Bereich erzeugt, der für Eingabe 4 (gerade) geordnet und zentriert ist, -2 -1 1 2
für Eingabe 5 (ungerade) erzeugt, erzeugt -2.5 -1.5 0 1 2
nur, dass sie geordnet und zentriert sein sollte

f(x)'+f(y)*i    

eine komplexe Matrix, die aus Bereichen generiert wird

(-2,-2.5) (-2,-1.5) (-2,0) (-2,1) (-2,2)
(-1,-2.5) (-1,-1.5) (-1,0) (-1,1) (-1,2)
(1,-2.5)  (1,-1.5)  (1,0)  (1,1)  (1,2)
(2,-2.5)  (2,-1.5)  (2,0)  (2,1)  (2,2)

t=angle(f(x)'+f(y)*i);                    

Rechnen Sie rechteckige Koordinaten in Polarkoordinaten um und geben Sie die Winkel zurück, sodass sie für jeden Ring gegen den Uhrzeigersinn sortiert werden

-2.25  -2.50  3.14  2.68  2.36
-1.95  -2.16  3.14  2.36  2.03
-1.19  -0.98  0.00  0.79  1.11
-0.90  -0.64  0.00  0.46  0.79


B=!!M;
B(2:x-1,2:y-1)=0;

Die folgende Matrix wurde generiert

1   1   1   1   1
1   0   0   0   1
1   0   0   0   1
1   1   1   1   1

d=bwdist(B,'chessboard');

Berechnet die Distanztransformation von B unter Verwendung der Schachbrettdistanz, um Ringindizes zu generieren

0   0   0   0   0
0   1   1   1   0
0   1   1   1   0
0   0   0   0   0               

Für eine 6 * 7-Matrix haben wir die folgende Matrix

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

[~,I]=sortrows([d(:) t(:)]);

lexikografische Sortierung zuerst basierend auf dem Ringindex und dann nach Winkel (Indizes der zurückgegebenen sortierten Elemente)

    for k=0:max(d(:))
        M(h)=shift(M(h=I(d(I)==k)),R);
    end

und schließlich jeden Ring kreisförmig verschieben.


4

Python 3, 292 288 Bytes

_=eval
a=input().split()
b,a=int(a[0]),_("".join(a[1:]))[::-1]
c=len(a)
d=len(a[0])
e=range
f="int((i>=j and i+j<c-1)|2*(i>=c/2and i+d>j+c)|3*(i<c/2and i+j<d))"
l=[-1,1,0,0],[0,0,1,-1]
g=lambda x:[[x[i+l[0][_(f)]][j+l[1][_(f)]]for j in e(d)]for i in e(c)]
print(_("g("*b+"a"+")"*b)[::-1])

Nimmt Eingaben mit entfernten Zeilenumbrüchen vor, lässt jedoch ein Leerzeichen nach der Anzahl der Schritte, um die die Eingabe gedreht werden soll.

Erläuterung:

Anstatt die Matrix gemäß dem Vorschlag des OP als eine Reihe konzentrischer Ringe zu modellieren, kann man sie stattdessen in vier Bereiche unterteilen, in denen sich die Elemente während einer einzelnen Drehung entweder nach oben, unten, rechts oder links bewegen. Dies ist der Zweck der langen bewerteten Zeichenfolge f: um zu bestimmen, in welche Region jede i,jKombination fällt. Das Ergebnis wird dann zweimal in nachgeschlagen l, wodurch das Element erhalten wird, i,jdas im nächsten Schritt in Position gedreht werden muss . Die Funktion g, die all dies ausführt und nach einem einzelnen Schritt die neue Matrix bildet, wird dann wiederholt aufgerufen, indem eine generierte Zeichenfolge ausgewertet wird, die die Darstellung eines verschachtelten Funktionsaufrufs enthält.

Als ich das ursprünglich gemacht habe, habe ich versehentlich die Matrix im Uhrzeigersinn anstatt gegen den Uhrzeigersinn gedreht. Anstatt eine ordnungsgemäße Korrektur vorzunehmen, habe ich zwei strategisch platzierte Kopien von hinzugefügt [::-1], um die Matrix vor und nach der Drehung umzukehren. Diese könnten wahrscheinlich auf ~ 280 golfen werden 276 Bytes , aber ich bin zu faul, um das zu tun.

Dies ist auch ein schneller, nicht getesteter Port aus einem etwas längeren Python 2-Programm. Verzeih mir, wenn er nicht richtig funktioniert. Hier ist sowieso der Python 2-Code:

_=eval
a=raw_input().split()
b,a=int(a[0]),_("".join(a[1:]))[::-1]
c=len(a)
d=len(a[0])
e=xrange
f="int((i>=j and i+j<c-1)|2*(i>=c/2and i+d>j+c)|3*(i<c/2and i+j<d))"
l=[-1,1,0,0],[0,0,1,-1]
g=lambda x:[[x[i+l[0][_(f)]][j+l[1][_(f)]]for j in e(d)]for i in e(c)]
print _("g("*b+"a"+")"*b)[::-1]

EDIT: golfed aus 4 Bytes durch den Austausch ormit |zweimal. andkann leider nicht geholfen werden.


Willkommen bei PPCG! Schöner erster Beitrag!
HyperNeutrino

Eigentlich eine lustige Geschichte - in meiner heutigen Highschool-Blaskapelle haben wir eine Formation gelernt, in der sich alle in konzentrischen rechteckigen "Ringen" bewegen, ähnlich wie bei dieser Frage, und ich dachte sofort an diese Antwort.
Aidan F. Pierce

1

Perl, 330 328 Bytes

sub f{($r,$m)=@_;$h=@m=@$m;for$s(0..(($w=$#{$m[0]})<--$h?$w:$h)/2-.5){@_=(@{$m[$s]}[@x=$s..($x=$w-$s)],(map$m[$_][$x],@y=1+$s..($y=$h-$s)-1),reverse(@{$m[$y]}[@x]),(map$m[$h-$_][$s],@y));push@_,shift
for 1..$r;@{$m[$s]}[@x]=map shift,@x;$m[$_][$x]=shift for@y;@{$m[$y]}[@x]=reverse map shift,@x;$m[$h-$_][$s]=shift for@y}@$m=@m}

Probieren Sie es auf Ideone .

Ungolfed:

sub f {
    my ($r, $m) = @_;

    my @m = @$m;
    my $h = $#m;
    my $w = @{$m[0]} - 1;
    my $c = (($w < $h ? $w : $h) + 1) / 2 - 1;

    for my $s (0 .. $c) {
        my $x = $w - $s;
        my $y = $h - $s;
        my @x = $s .. $x;
        my @y = $s + 1 .. $y - 1;

        # One circle.
        @_ = (@{$m[$s]}[@x],
              (map { $m[$_][$x] } @y),
              reverse(@{$m[$y]}[@x]),
              (map { $m[$h - $_][$s] } @y));

        # Circular shift.
        push(@_, shift(@_)) for 1 .. $r;

        @{$m[$s]}[@x] = map { shift(@_) } @x;
        $m[$_][$x] = shift(@_) for @y;
        @{$m[$y]}[@x] = reverse(map { shift(@_) } @x);
        $m[$h - $_][$s] = shift(@_) for @y;
    }

    @$m = @m;
}
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.