¡Cuidado con el tornado matricial!

27

El tornado matricial es como cualquier otro tornado: consiste en cosas que giran alrededor de un centro. En este caso, elementos de la matriz en lugar de aire.

Aquí hay un ejemplo de un tornado matricial:

Tornado matricial en acción

Primero comenzamos seccionando la matriz en anillos cuadrados, cada sección consta de elementos que están más lejos del borde en la misma distancia. Estas secciones se rotarán en sentido horario alrededor del centro. En los tornados reales, la gravedad aumenta hacia el centro, y también lo hace el paso de rotación en un tornado matricial: la sección más externa (la roja) gira 1 paso, la siguiente (la amarilla) gira 2, y así en. Un paso de rotación es una rotación de 90 ° alrededor del centro.

Tarea:

Su tarea, si la acepta, es escribir una función o programa que tome como entrada una matriz cuadrada, aplicarle el efecto tornado y luego generar la matriz resultante.

Entrada:

La entrada debe ser una matriz cuadrada de orden ndonde n >= 1. No se debe suponer acerca de los elementos de la matriz, podrían ser cualquier cosa.

Salida:

Una matriz cuadrada del mismo orden que sería el resultado de aplicar el efecto tronado a la matriz de entrada.

Ejemplos:

Una matriz de orden n = 1:

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

Una matriz de orden n = 2:

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

Una matriz de orden 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]]
ibrahim mahrir
fuente
Creo que quiere aclarar que las rotaciones son de 90 °.
Erik the Outgolfer
Además, ¿has tomado este desafío desde otro lugar? Si es así, debe proporcionar la atribución.
Erik the Outgolfer
1
@EriktheOutgolfer 1) Lo he aclarado. 2) Este desafío es mío.
ibrahim mahrir
44
@Giuseppe Depende del hemisferio en el que te encuentres;)
Jo King
12
Primero me gustaría decir que creo que este es un buen desafío: ¡buen trabajo! Pero también me gustaría conectar este punto porque creo que su decisión de decir que podría ser cualquier tipo de datos deja su desafío en un lugar incómodo. De manera similar, con su afirmación acerca de que la entrada es una lista de listas, ha restringido los idiomas que pueden resolver este problema sin tener que hacer un trabajo general. Creo que el desafío es mejor si estos requisitos se relajan. ¡Espero que sigas publicando buenos desafíos como este! :)
FryAmTheEggman

Respuestas:

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

Pruébalo en línea!

Aneesh Durg
fuente
8
Python clásico, simplemente cayendo a[1:-1,1:-1]=f(a[1:-1,1:-1])como si fuera la cosa más normal del mundo obtener y configurar directamente todo el interior de una matriz bidimensional
ETHproductions
1
@ETHproductions Para ser justos, parte de eso es la sintaxis heredada denumpy
Jo King el
1
numpy.rot90(a,1,(1,0))es más corto en 3 bytes y también debería funcionar.
Graipher
1
¿Cuál es el punto del enlace TIO sin ningún caso de prueba? ..: S Aquí está con (dejó el espacio en if len(a):a=...-1 byte).
Kevin Cruijssen
5

Carbón , 44 bytes

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

Pruébalo en línea! El enlace es a la versión detallada del código. Solo funciona en cuadrados de caracteres porque la E / S predeterminada de Charcoal no hace justicia a las matrices normales. Explicación:

≔EθSθ

Lee el cuadrado del personaje.

Wθ«

Bucle hasta que esté vacío.

≔Eθ⮌⭆觧θνλθ

Rota lo.

θM¹⁻¹Lθ

Imprímelo, pero luego mueve el cursor a un cuadrado en diagonal desde la esquina original.

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

Recorte el exterior de la matriz.

Neil
fuente
5

Jalea , 27 bytes

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

Pruébalo en línea!

Creo que esto podría ser mucho más corto.

           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.
Lynn
fuente
1
Probablemente pueda poner µGel pie de página y afirmar que su presentación es 25.
Sr. Xcoder
5

Perl 6 , 78 73 72 bytes

¡Gracias a nwellnhof por -5 bytes!

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

Pruébalo en línea!

Bloque de código recursivo que toma una matriz 2D aplanada y devuelve una matriz aplanada de manera similar.

Explicación:

$!={      # 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
}
Jo King
fuente
Puede usar en @a[*;*]lugar de map |*,@aaplanar la matriz. (Sería bueno si hubiera una manera de trabajar con matrices no planas y subíndices multidimensionales, pero no puedo pensar en una)
nwellnhof
Pero @a[1..*-2;1..@a-2].=$!funciona.
nwellnhof el
5

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

Pruébalo en línea!

Soy consciente de que las funciones anónimas recursivas no son el método más corto para hacer cosas en Octave, pero son el método más divertido con diferencia. Esta es la función anónima más corta que se me ocurrió, pero me encantaría que me superaran.

Explicación

La función recursiva se define de acuerdo con esta respuesta de de ceilingcat. q=f(f=@(g)@(M) ... g(g)(M) ...es la estructura básica de dicha función anónima, con g(g)(M)la llamada recursiva. Ya que esto recursivo indefinidamente, envolvemos la llamada recursiva en una serie de células condicional: {@()g(g)(M),M}{condition}(). La función anónima con la lista de argumentos vacía retrasa la evaluación después de que se haya seleccionado la condición (aunque más adelante, vemos que podemos usar esa lista de argumentos para definir z). Hasta ahora solo ha sido la contabilidad básica.

Ahora para el trabajo real. Queremos que la función devuelva rot90(P,-1)con P una matriz en la que g(g)se ha llamado recursivamente en la parte central de M. Comenzamos por establecer z=2:end-1qué podemos ocultar en la indexación de M. De esta manera, M(z,z)selecciona la parte central de la matriz que necesita ser tornado aún más por una llamada recursiva. La ,3parte asegura que las rotaciones sean en sentido horario. Si vives en el hemisferio sur, puedes eliminar este bit por -2 bytes.

Entonces lo hacemos M(z,z)=g(g)M(z,z). Sin embargo, el valor resultante de esta operación es solo la parte central modificada en lugar de la Pmatriz completa . Por lo tanto, hacemos{M(z,z)=g(g)M(z,z),M}{2} que básicamente es robado de esta respuesta de de Stewie Griffin.

Finalmente, el condition es solo que la recursión se detiene cuando la entrada está vacía.

Sanchises
fuente
+1 para el hemisferio sur
ceilingcat
Todavía no he tratado de entender la recursión en funciones anónimas, por lo que no lo intentaré, pero tengo curiosidad por ver si la recursividad es más corta que los bucles en esta .
Stewie Griffin
@StewieGriffin veré lo que puedo hacer :)
Sanchises
@StewieGriffin Por cierto, siéntase desafiado a publicar una versión basada en bucle para este desafío en Octave. Realmente me pregunto si puedes vencer el enfoque recursivo.
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}

Pruébalo en línea!

digEmAll
fuente
¿Esta permitido? La imagen muestra una flecha en el sentido de las agujas del reloj y la descripción a continuación indica la rotación en el sentido de las agujas del reloj ...
digEmAll
Debo haber leído la pregunta diez veces y nunca me di cuenta de que dice en el sentido de las agujas del reloj (de ahí mi comentario). Ay.
Giuseppe
Eheh, cuéntame sobre eso ... Soy el rey de leer mal las publicaciones: D
digEmAll
1
Desafortunadamente, la matriz 1x1 no funcionará (porque seq(0.5)devuelve 1 en lugar de un vector vacío)
digEmAll
4

MATL , 25 24 23 22

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

Pruébalo en línea!

La indexación en MATL nunca es fácil, pero con algo de golf en realidad supera la mejor respuesta actual de Jelly ...

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. 

* Para una n x nmatriz, este programa realiza niteraciones, mientras que realmente solo necesita n/2rotaciones. Sin embargo, la indexación en MATL (AB) es lo suficientemente flexible como para que la indexación de rangos imposibles sea simplemente no operativa. De esta manera, no es necesario desperdiciar bytes para obtener el número de iteraciones correcto.

Sanchises
fuente
3

K (ngn / k) , 41 39 38 bytes

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

Pruébalo en línea!

{ } funcionar con argumento x

#xlongitud de x- la altura de la matriz

2##x dos copias: alto y ancho (se supone que es lo mismo)

s:asignar a spara "forma"

!stodos los índices de una matriz con forma s, por ejemplo, !5 5es

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

Esta es una matriz de 2 filas (lista de listas) y sus columnas corresponden a los índices en una matriz de 5x5.

&/ mínimo sobre las dos filas:

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:asignar a i, invertir ( |) y tomar mínimos ( &) 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

Estos son los números de anillo aplanados de una matriz de 5x5:

4!1+ suma 1 y toma resto módulo 4

(+|:)es una función que gira invirtiendo ( |- necesitamos :forzarla a ser monádica) y luego transponiendo ( +- ya que no es el verbo más a la derecha en el "tren", no necesitamos a :)

4(+|:)\x aplicarlo 4 veces en x , conservando resultados intermedios

,/' aplanar cada

+ transponer

( )@' indexar cada valor a la izquierda con cada valor a la derecha

s# remodelar a s

ngn
fuente
2
Estaré encantado de ver la explicación de su código
Galen Ivanov
1
@GalenIvanov Claro. No creo que pueda seguir jugando al golf, así que podría intentar explicarlo.
ngn
¡Gracias! Sus soluciones me dan ganas de comenzar a aprender k (o incluso ngn / k :))
Galen Ivanov
@GalenIvanov Estando familiarizado con J (y APL?), Ya está a medio camino. K es más pequeño y simple, por lo que recomiendo aprenderlo y, por supuesto, estoy feliz de conversar sobre ello en el Orchard en cualquier momento. ngn / k es solo un subconjunto de lo real, pero mi objetivo es hacerlo rápido y práctico.
ngn
Sí, creo que lo voy a probar.
Galen Ivanov
3

JavaScript (ES6), 99 bytes

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

Pruébalo en línea!

¿Cómo?

Dada una matriz cuadrada de ancho W, definimos:

metro=W-12tX,y=max(El |y-metroEl |,El |X-metroEl |)

Ejemplo de salida de tX,y para una matriz de 5x5 (W=5 5, metro=2):

(2222221112210 0122111222222)

Empezamos con k=metro y realizar una rotación de 90 ° en sentido horario de todas las celdas (X,y) satisfactorio:

tX,yk

mientras que los otros no se modifican.

Esto es equivalente a decir que una celda no gira si tenemos:

(y-metro>k) O (metro-y>k) O (X2>k2) con X=metro-X

cual es la prueba usada en el código:

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

Entonces decrementamos k y empezar de nuevo, hasta k=-1 o k=-3/ /2 (dependiendo de la paridad de W) De cualquier manera, desencadena nuestra condición de detención:

~k === 0
Arnauld
fuente
3

Jalea , 24 bytes

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

Pruébalo en línea!

Creo que esto podría ser mucho más corto.

- Lynn

Erik el Outgolfer
fuente
Me preguntaba sobre una solución como esta! Eso me ḷ""parece mágico ^^ ¿quieres agregar una explicación?
Lynn
@ Lynn Lo último que esperaba era escuchar que ḷ""es mágico. Es solo ḷ"con un extra "... oh, hay una pequeña posibilidad de que ḷ"también sea algo que "inventé" que no se haya usado tanto, ya que a menudo se puede reemplazar con un solo átomo (no en este caso, como el la entrada puede contener 0también).
Erik the 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

Pruébalo en línea!

Solía transposición de Laikoni y modificar un poco, para girar una matriz 90 °:

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

Explicación

r Rota una matriz 90 °.

(!)es una función de nivel superior: "aplicar al centro". g![1,2,3,4,5]es [1] ++ g[2,3,4] ++ [5].

f es la función tornado: los casos base son de tamaño 1 y 2 (de alguna manera 0 no funciona).

La última línea es donde ocurre la magia: aplicamos r.r.r.(f!).ren las filas del medio xy luego rotamos el resultado. Llamemos a las filas del medio M . Queremos recurrir en las columnas centrales de M , y para llegar a ellas, podemos rotar M y luego usar (f!). Luego usamos r.r.rpara rotar M nuevamente a su orientación original.

Lynn
fuente
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 gracias a @ceilingcat .

Pruébalo en línea.

Explicación:

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

bse usa básicamente para indicar en qué anillo estamos. Y luego rotará este anillo, incluyendo todo dentro de él una vez en el sentido de las agujas del reloj durante cada iteración.

El reemplazo de la matriz de entrada se realiza porque Java es paso por referencia, por lo que simplemente establecerlo r=msignificaría que ambas matrices se modifican al copiar desde las celdas, lo que causa resultados incorrectos. Por lo tanto, tenemos que crear una nueva Objectmatriz (nueva referencia) y copiar los valores en cada celda uno por uno.

Kevin Cruijssen
fuente
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

Estoy seguro de que esto se puede jugar un poco más de alguna manera.

Explicación

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
Jacob Watson
fuente
1

C (gcc) , 128 118 115 bytes

-15 bytes de @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);}

Pruébalo en línea!

vazt
fuente
1

Haskell, 274 bytes

w es la función principal, que tiene el tipo [[a]] -> [[a]] que esperarías.

Estoy seguro de que un golfista más experimentado de Haskell podría mejorar esto.

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
AlexJ136
fuente
Puede consultar nuestros consejos para jugar al golf en Haskell, por ejemplo, el uso de guardias en lugar de condicionales ahorrará algunos bytes.
Laikoni