Rotazione di una matrice 2D


30

Diciamo che ho la seguente matrice (2D):

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

Ruota le matrici in senso antiorario R (non con incrementi di 90 gradi, solo di 1 numero ogni volta),

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

Esempio completato:

Ingresso:

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

Produzione:

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

(spazi strani sono per allineare i numeri in belle colonne)

L '"anello" esterno della matrice ruota 2 in senso antiorario e anche la parte interna destra ruota 2. In questa matrice, ci sono solo due anelli.

Un esempio con 1 "anello":

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

Dovrebbe produrre:

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

La tua sfida è quella di prendere una matrice e un numero intero Re produrre la versione tradotta dopo le Rrotazioni.

La rotazione di una matrice 4x5 è rappresentata dalla figura seguente: inserisci qui la descrizione dell'immagine

vincoli:

  • 2 ≤ M, N ≤ 100, dove M e N sono le dimensioni della matrice. È garantito che il minimo di M e N sarà pari.
  • 1 ≤ R ≤ 80, dove r è il numero di rotazioni.
  • La matrice conterrà solo numeri interi positivi.
  • I valori non sono sempre distinti.
  • L'input dovrebbe essere sempre come un array 2D (se non puoi prendere l'input di runtime come un array 2D, devi solo trovare un altro modo per ottenere l'input).

Un altro caso di test, con valori non distinti:

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

Uscite:

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

Questo è , quindi vince la risposta più breve!





4
@ceasedtoturncounterclockwis Il tuo nome è molto ironico per questa sfida ...
HyperNeutrino

1
[[3, 4, 8, 12], [2, 11, 10, 16], [1, 7, 6, 16], [5, 9, 13, 14]]il 16 è improvvisamente duplicato immagino che dovrebbe essere [[3, 4, 8, 12], [2, 11, 10, 16], [1, 7, 6, 15], [5, 9, 13, 14]]:?
Christoph

Risposte:



5

Ottava, 210 byte

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

Provalo su Octave Online!

Versione non golfata:

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)

Spiegazione:

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

Una funzione che ottiene un numero e genera un intervallo ordinato e centrato per l'ingresso 4 (pari) genera -2 -1 1 2
per l'ingresso 5 (dispari) genera -2.5 -1.5 0 1 2
solo che deve essere ordinato e centrato

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

una matrice complessa generata da intervalli

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

Converti le coordinate rettangolari in polari e restituisci gli angoli in modo che per ogni anello gli angoli vengano ordinati in senso antiorario

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

La seguente matrice generata

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

d=bwdist(B,'chessboard');

Calcola la trasformazione della distanza di B usando la distanza della scacchiera per generare indici di anello

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

per una matrice 6 * 7 avremo la seguente matrice

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(:)]);

ordinamento lessicografico prima basato sull'indice dell'anello e poi per ordine dell'angolo (restituiti gli indici degli elementi ordinati)

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

e infine spostare circolare ogni anello.


4

Python 3, 292 288 byte

_=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])

Accetta l'input con le nuove righe rimosse, ma lasciando uno spazio dopo il numero di incrementi per ruotarlo di.

Spiegazione:

Invece di modellare la matrice come una serie di anelli concentrici secondo il suggerimento del PO, si può invece dividerlo in quattro regioni in cui gli elementi viaggiano su, giù, destra o sinistra durante una singola rotazione. Questo è lo scopo della lunga stringa valutata f: determinare in quale regione i,jrientra ciascuna combinazione. Quindi, il risultato viene guardato due volte dentro l, dando l'elemento che deve ruotare in posizione i,jnel passaggio successivo. La funzione gche esegue tutto ciò e forma la nuova matrice dopo un singolo passaggio viene quindi chiamata ripetutamente valutando una stringa generata contenente la rappresentazione di una chiamata di funzione nidificata.

Quando l'ho realizzato originariamente, ho causato la rotazione accidentale della matrice in senso orario anziché antiorario. Invece di fare una correzione corretta, ho aggiunto due copie posizionate strategicamente [::-1]per invertire la matrice prima e dopo la rotazione. Probabilmente questi potrebbero essere giocati a ~ 280 276 byte, ma sono troppo pigro per farlo.

Inoltre, questa è una porta non testata rapida da un programma Python 2 leggermente più lungo, quindi perdonami se non funziona abbastanza bene. Ecco il codice Python 2, comunque:

_=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: golfato di 4 byte sostituendolo orcon |due volte. andpurtroppo non può essere aiutato.


Benvenuti in PPCG! Bel primo post!
HyperNeutrino

Storia divertente in realtà - nella mia banda musicale del liceo oggi abbiamo imparato una formazione in cui tutti si muovono in "anelli" concentrici rettangolari simili a questa domanda, e ho subito pensato a questa risposta.
Aidan F. Pierce,

1

Perl, 330 328 byte

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}

Provalo su 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;
}
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.