Cuidado com o furacão da matriz!

27

O tornado da matriz é como qualquer outro tornado: consiste em coisas que giram em torno de um centro. Nesse caso, elementos da matriz em vez de ar.

Aqui está um exemplo de um furacão da matriz:

Tornado de matriz em ação

Primeiro, começamos o corte da matriz em anéis quadrados, cada seção consiste em elementos que estão mais distantes da borda pela mesma distância. Essas seções serão giradas no sentido horário em torno do centro. Em tornados reais, a gravidade aumenta em direção ao centro, assim como a etapa de rotação em um tornado de matriz: a seção mais externa (a vermelha) é girada em 1 etapa, a próxima (a amarela) é girada por 2, e assim em. Um passo de rotação é uma rotação de 90 ° em torno do centro.

Tarefa:

Sua tarefa, se você a aceitar, é escrever uma função ou programa que tome como entrada uma matriz quadrada, aplique o efeito tornado a ela e, em seguida, produza a matriz resultante.

Entrada:

A entrada deve ser uma matriz quadrada de ordem nonde n >= 1. Nenhuma suposição deve ser feita sobre os elementos da matriz, eles podem ser qualquer coisa.

Saída:

Uma matriz quadrada da mesma ordem que seria o resultado da aplicação do efeito tronado à matriz de entrada.

Exemplos:

Uma matriz de ordem n = 1:

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

Uma matriz de ordem n = 2:

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

Uma matriz de ordem 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
fonte
Eu acho que você quer esclarecer que as rotações são rotações de 90 °.
Erik the Outgolfer
Além disso, você aceitou esse desafio de outro lugar? Nesse caso, você deve fornecer a atribuição.
Erik the Outgolfer
1
@EriktheOutgolfer 1) Esclareci isso. 2) Esse desafio é meu.
ibrahim mahrir
4
@ Giuseppe Depende do hemisfério em que você está #;)
Jo King
12
Primeiro, gostaria de dizer que acho um bom desafio: bom trabalho! Mas eu também gostaria de acrescentar esse ponto, porque acho que sua escolha de dizer que poderia ser qualquer tipo de dado deixa seu desafio em um local estranho. Da mesma forma, com sua declaração de que a entrada é uma lista de listas, você restringiu os idiomas que podem resolver esse problema sem fazer um trabalho adicional. Eu acho que o desafio é melhor se esses requisitos forem relaxados. Espero que você continue postando bons desafios como este! :)
FryAmTheEggman

Respostas:

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

Experimente online!

Aneesh Durg
fonte
8
Clássico Python, apenas caindo a[1:-1,1:-1]=f(a[1:-1,1:-1])como se fosse a coisa mais normal do mundo para directamente obter e definir todo o interior de uma matriz 2-dimensional
ETHproductions
1
@ETHproductions Para ser justo, parte disso é herdada da sintaxe denumpy
Jo King
1
numpy.rot90(a,1,(1,0))é mais curto em 3 bytes e também deve funcionar.
Graipher
1
Qual é o sentido do link TIO sem nenhum caso de teste? ..: S Aqui está com (diminuiu o espaço if len(a):a=...para -1 byte).
Kevin Cruijssen
5

Carvão , 44 bytes

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

Experimente online! Link é a versão detalhada do código. Só funciona nos quadrados de caracteres porque a E / S padrão do Charcoal não faz justiça às matrizes normais. Explicação:

≔EθSθ

Leia o quadrado dos caracteres.

Wθ«

Faça um loop até ficar vazio.

≔Eθ⮌⭆觧θνλθ

Girá-lo.

θM¹⁻¹Lθ

Imprima, mas mova o cursor para um quadrado na diagonal a partir do canto original.

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

Apare a parte externa da matriz.

Neil
fonte
5

Gelatina , 27 bytes

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

Experimente online!

Eu acho que isso poderia ser muito menor.

           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
fonte
1
Você provavelmente pode simplesmente colocar µGno rodapé e alegação de que sua submissão é 25.
Mr. Xcoder
5

Perl 6 , 78 73 72 bytes

Obrigado ao nwellnhof por -5 bytes!

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

Experimente online!

Bloco de código recursivo que pega uma matriz 2D achatada e retorna uma matriz achatada da mesma forma.

Explicação:

$!={      # 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
}
Brincadeira
fonte
Você pode usar em @a[*;*]vez de map |*,@aachatar a matriz. (Seria bom se houvesse uma maneira de trabalhar com matrizes não-achatadas e subscritos multi-dimensão, mas eu não posso pensar em um.)
nwellnhof
Mas @a[1..*-2;1..@a-2].=$!funciona.
Nwellnhof 1/08
5

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

Experimente online!

Estou ciente de que funções anônimas recursivas não são o método mais curto para fazer as coisas no Octave, mas são o método mais divertido de longe. Essa é a menor função anônima que eu poderia ter, mas adoraria ser derrotada.

Explicação

A função recursiva é definida de acordo com estas respondidas pelo tetocat. q=f(f=@(g)@(M) ... g(g)(M) ...é a estrutura básica de uma função anônima, com g(g)(M)a chamada recursiva. Uma vez que este seria recurse indefinidamente, nós envolvemos a chamada recursiva em uma matriz de célula condicional: {@()g(g)(M),M}{condition}(). A função anônima com lista de argumentos vazia atrasa a avaliação para após a seleção da condição (embora mais tarde, vejamos que podemos usar essa lista de argumentos para definir z). Até agora, foi apenas a contabilidade básica.

Agora, para o trabalho real. Queremos que a função retorne rot90(P,-1)com P uma matriz na qual g(g)foi chamada recursivamente na parte central de M. Começamos definindo o z=2:end-1que podemos ocultar na indexação de M. Dessa forma, M(z,z)seleciona a parte central da matriz que precisa ser ser tornado ainda mais por uma chamada recursiva. A ,3peça garante que as rotações estejam no sentido horário. Se você mora no hemisfério sul, pode remover esse bit por -2 bytes.

Nós fazemos então M(z,z)=g(g)M(z,z). No entanto, o valor resultante desta operação é apenas a parte central modificada, e não a Pmatriz inteira . Por isso, fazemos o {M(z,z)=g(g)M(z,z),M}{2}que é basicamente roubado desta resposta de de Stewie Griffin.

Finalmente, a conditionrecursão para quando a entrada está vazia.

Sanchises
fonte
+1 para o hemisfério sul
roofcat
Ainda não tentei entender a recursão em funções anônimas, por isso não tentarei, mas estou curioso para ver se a recursão é mais curta do que os loops nesta .
Stewie Griffin
@StewieGriffin Vou ver o que posso fazer :)
Sanchises
@StewieGriffin A propósito, sinta-se desafiado a publicar uma versão baseada em loop para esse desafio no Octave. Eu realmente me pergunto se você pode vencer a abordagem recursiva.
Sanchises 20/09
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}

Experimente online!

digEmAll
fonte
Isso é permitido? A imagem mostra uma seta no sentido horário e a descrição abaixo indica a rotação no sentido horário ...
digEmAll 1/18
Devo ter lido a pergunta dez vezes e nunca a notei no sentido horário (daí o meu comentário). Alas.
Giuseppe
Eheh, diga-me sobre isso ... Eu sou o rei de mensagens leitura errada: D
digEmAll
1
Infelizmente, a matriz 1x1 não irá funcionar (devido seq(0.5)retornos 1 em vez de vector vazio)
digEmAll
4

MATL , 25 24 23 22

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

Experimente online!

A indexação no MATL nunca é fácil, mas com alguns jogos de golfe ele realmente supera a melhor resposta atual da 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 uma n x nmatriz, este programa faz niterações, enquanto você realmente precisa apenas de n/2rotações. No entanto, a indexação em MATL (AB) é suficientemente flexível para que a indexação de faixas impossíveis seja apenas um não-op. Dessa forma, não há necessidade de desperdiçar bytes para obter o número correto de iterações.

Sanchises
fonte
3

Python 2 , 98 bytes

def f(a):
 if a:a=zip(*a[::-1]);b=zip(*a[1:-1]);b[-2:0:-1]=f(b[-2:0:-1]);a[1:-1]=zip(*b)
 return a

Experimente online!

TFeld
fonte
3

K (ngn / k) , 41 39 38 bytes

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

Experimente online!

{ } função com argumento x

#xcomprimento de x- a altura da matriz

2##x duas cópias - altura e largura (assumida a mesma)

s:atribuir a s"forma"

!stodos os índices de uma matriz com forma s, por exemplo, !5 5é

(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 é uma matriz de 2 linhas (lista de listas) e suas colunas correspondem aos índices em uma matriz 5x5.

&/ mínimo nas duas linhas:

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:atribua a i, reverse ( |) e use minima (& ) comi

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

Estes são os números dos anéis achatados de uma matriz 5x5:

4!1+ adicione 1 e pegue os restantes módulos 4

(+|:)é uma função que gira revertendo ( |- precisamos :forçá-lo a ser monádico) e depois transpondo ( +- já que não é o verbo mais à direita no "trem", não precisamos de um: )

4(+|:)\x aplique-o 4 vezes em x , preservando resultados intermediários

,/' achatar cada

+ transpor

( )@' indexe cada valor à esquerda com cada valor à direita

s# remodelar para s

ngn
fonte
2
Ficarei feliz em ver a explicação do seu código
Galen Ivanov
1
@GalenIvanov Claro. Eu não acho que posso jogar mais isso, então eu poderia tentar explicar isso.
ngn
Obrigado! Suas soluções me fazem querer começar a aprender k (ou até ngn / k :))
Galen Ivanov
@GalenIvanov Por estar familiarizado com J (e APL?), Você já está no meio do caminho. K é menor e mais simples, então eu recomendo aprendê-lo e, é claro, fico feliz em conversar sobre isso no Orchard a qualquer momento. ngn / k é apenas um subconjunto da coisa real, mas pretendo torná-la rápida e prática.
ngn
Sim, acho que vou tentar.
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

Experimente online!

Quão?

W

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

tx,yW=5m=2

(2222221112210 0122111222222)

k=m(x,y)

tx,yk

enquanto os outros permanecem inalterados.

Isso é equivalente a dizer que uma célula é nãogirada se tivermos:

(y-m>k) OU (m-y>k) OU (X2>k2) com X=m-x

qual é o teste usado no 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
  )
)

kk=1k=3/2W

~k === 0
Arnauld
fonte
3

Gelatina , 24 bytes

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

Experimente online!

Eu acho que isso poderia ser muito menor.

- Lynn

Erik, o Outgolfer
fonte
Gostaria de saber sobre uma solução como esta! Isso ḷ""parece mágico para mim ^^ gostaria de adicionar uma explicação?
Lynn
@ Lynn A última coisa que eu esperava era ouvir isso ḷ""é mágico. É apenas ḷ"com um extra "... oh, há uma pequena possibilidade de que ḷ"também "inventei" algo que não tenha sido usado tanto, pois muitas vezes pode ser substituído por um único átomo (não neste caso, como o entrada também pode conter 0).
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

Experimente online!

I utilizados de transposição do Laikoni e modificou-se um pouco, para rodar uma matriz de 90 °:

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

Explicação

r gira uma matriz em 90 °.

(!)é uma função de nível superior: "aplicar ao centro". g![1,2,3,4,5]é [1] ++ g[2,3,4] ++ [5].

f é a função tornado: os casos base são do tamanho 1 e 2 (de alguma forma, 0 não funciona).

A última linha é onde a mágica acontece: aplicamos r.r.r.(f!).rnas linhas do meio xe depois giramos o resultado. Vamos chamar as linhas médias M . Queremos recuar nas colunas do meio de M e, para chegar a elas, podemos girar M e depois usar (f!). Em seguida, usamos r.r.rpara girar M de volta à sua orientação original.

Lynn
fonte
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 graças a @ceilingcat .

Experimente online.

Explicação:

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

bé basicamente usado para indicar em qual anel estamos. E ele girará esse anel, incluindo tudo dentro dele uma vez no sentido horário durante cada iteração.

A substituição da matriz de entrada é feita porque o Java é transmitido por referência; portanto, a simples configuração r=msignifica que as duas matrizes são modificadas ao copiar das células, causando resultados incorretos. Portanto, temos que criar um novoObject matriz (nova referência) e copiar os valores em cada célula, um por um.

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

Tenho certeza de que isso pode ser jogado de alguma forma.

Explicação

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
fonte
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);}

Experimente online!

vazt
fonte
1

Haskell, 274 bytes

w é a função principal, que tem o tipo [[a]] -> [[a]] que você esperaria.

Tenho certeza de que um jogador de golfe Haskell mais experiente poderia melhorar isso.

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
fonte
Você pode conferir nossas dicas para jogar golfe em Haskell, por exemplo, usar guardas em vez de condicionais economizará alguns bytes.
Laikoni