Rotation d'une matrice 2D

30

Disons que j'ai la matrice (2D) suivante:

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

Faites pivoter la matrice dans le sens antihoraire R (pas par incréments de 90 degrés, juste d'un chiffre à chaque fois),

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

Exemple complété:

Contribution:

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

Sortie:

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

(les espaces étranges sont pour aligner les nombres dans de belles colonnes)

L '«anneau» extérieur de la matrice tourne de 2 dans le sens antihoraire, et l'intérieur de droite tourne également de 2. Dans cette matrice, il n'y a que deux anneaux.

Un exemple avec 1 "anneau":

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

Devrait produire:

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

Votre défi est de prendre une matrice et un entier R, et de sortir la version traduite après les Rrotations.

La rotation d'une matrice 4x5 est représentée par la figure suivante: entrez la description de l'image ici

Contraintes:

  • 2 ≤ M, N ≤ 100, où M et N sont les dimensions de la matrice. Il est garanti que le minimum de M et N sera pair.
  • 1 ≤ R ≤ 80, où r est le nombre de rotations.
  • La matrice ne contiendra que des nombres entiers positifs.
  • Les valeurs ne sont pas toujours distinctes.
  • L'entrée doit toujours être sous forme de tableau 2D (si vous ne pouvez pas prendre l'entrée d'exécution en tant que tableau 2D, il vous suffit de trouver un autre moyen d'obtenir l'entrée).

Un autre cas de test, avec des valeurs non distinctes:

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

Les sorties:

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

Il s'agit de , donc la réponse la plus courte l'emporte!

StepUp
la source
En relation
Peter Taylor
En relation.
Martin Ender
2
En relation.
cessé de tourner dans le sens inverse des aiguilles d'une montre
4
@ceasedtoturncounterclockwis Votre nom est très ironique pour ce défi ...
HyperNeutrino
1
[[3, 4, 8, 12], [2, 11, 10, 16], [1, 7, 6, 16], [5, 9, 13, 14]]le 16 est soudainement dupliqué je suppose que ça devrait être [[3, 4, 8, 12], [2, 11, 10, 16], [1, 7, 6, 15], [5, 9, 13, 14]]:?
Christoph

Réponses:

5

Octave, 210 octets

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

Essayez-le sur Octave Online!

Version non golfée:

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)

Explication:

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

Une fonction qui obtient un nombre et génère une plage ordonnée et centrée pour l'entrée 4 (paire) génère -2 -1 1 2
pour l'entrée 5 (impaire) génère -2.5 -1.5 0 1 2
uniquement elle doit être ordonnée et centrée

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

une matrice complexe générée à partir de plages

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

Convertissez les coordonnées rectangulaires en coordonnées polaires et retournez les angles de sorte que pour chaque anneau, les angles soient triés dans le sens inverse des aiguilles d'une montre

-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 matrice suivante a généré

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

d=bwdist(B,'chessboard');

Calcule la transformation de distance de B en utilisant la distance de l'échiquier pour générer des indices d'anneau

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

pour une matrice 6 * 7 nous aurons la matrice suivante

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

tri lexicographique basé d'abord sur l'index de l'anneau puis par ordre d'angle (index des éléments triés retournés)

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

et enfin un décalage circulaire de chaque anneau.

rahnema1
la source
4

Python 3, 292 288 octets

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

Prend l'entrée avec les nouvelles lignes supprimées, mais en laissant un espace après le nombre d'incréments pour le faire pivoter.

Explication:

Au lieu de modéliser la matrice comme une série d'anneaux concentriques selon la suggestion de l'OP, on peut plutôt la diviser en quatre régions où les éléments se déplacent vers le haut, le bas, la droite ou la gauche pendant une seule rotation. C'est le but de la longue chaîne évaluée f: pour déterminer dans quelle région chaque i,jcombinaison se trouve. Ensuite, le résultat est recherché deux fois l, ce qui donne l'élément qui doit tourner en position i,jà l'étape suivante. La fonction gqui fait tout cela et forme la nouvelle matrice après une seule étape est ensuite appelée à plusieurs reprises en évaluant une chaîne générée contenant la représentation d'un appel de fonction imbriquée.

Lorsque j'ai fait cela à l'origine, j'ai accidentellement fait pivoter la matrice dans le sens horaire plutôt que dans le sens antihoraire. Plutôt que de faire une correction correcte, j'ai ajouté deux copies stratégiquement placées de [::-1]pour inverser la matrice avant et après la rotation. Ceux-ci pourraient probablement être limités à ~ 280 276 octets, mais je suis trop paresseux pour le faire.

En outre, il s'agit d'un port non testé rapide d'un programme Python 2 légèrement plus long, alors pardonnez-moi si cela ne fonctionne pas tout à fait correctement. Voici le code Python 2, de toute façon:

_=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 off 4 octets en remplaçant orpar |deux. andne peut pas être aidé, malheureusement.

Aidan F. Pierce
la source
Bienvenue chez PPCG! Bon premier post!
HyperNeutrino
Histoire drôle en fait - dans ma fanfare du lycée aujourd'hui, nous avons appris une formation où tout le monde se déplace en "anneaux" concentriques rectangulaires similaires à cette question, et j'ai immédiatement pensé à cette réponse.
Aidan F. Pierce
1

Perl, 330 328 octets

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}

Essayez-le sur Ideone .

Non golfé:

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;
}
Denis Ibaev
la source