Emita a espiral interna anti-horária de uma matriz 2D

15

A partir desta pergunta stackoverflow

Dada uma matriz 2D do tamanho M×N , produza os valores no sentido anti-horário. A saída deve começar de fora para dentro e o ponto inicial sempre será (0 0,0 0) .

Exemplo dado:

[12345678910111213141516]

Os valores das arestas no sentido anti-horário são então 1,5,9,13,14,15,16,12,8,4,3,2 .

Agora repetimos o processo para os valores internos. Isso terminará com uma matriz como a seguinte

[671011]

E os valores internos são então 6,10,11,7

O resultado final será então 1,5,9,13,14,15,16,12,8,4,3,2,6,10,11,7


Regras

  • Assumir entrada não vazia
  • Assuma valores de matriz como números inteiros positivos
  • Aplicam-se métodos de E / S padrão
  • Aplicam regras padrão de e os critérios de vencimento

Alguns casos de teste

Input
[
  [1, 2, 3, 4, 5, 6, 7],
  [8, 9, 10,11,12,13,14],
  [15,16,17,18,19,20,21]
]
Output
1,8,15,16,17,18,19,20,21,14,7,6,5,4,3,2,9,10,11,12,13

--------------------------------------------------------

Input
[
    [1,2,3],
    [3,2,1],
    [4,5,6],
    [6,5,4],
    [7,8,9],
    [9,8,7]
]
Output
1,3,4,6,7,9,8,7,9,4,6,1,3,2,2,5,5,8

-----------------------------------------------------
Input
[
    [1]
]
Output
1
-----------------------------------
Input
[
    [1, 2],
    [2, 1]
]
Output
1,2,1,2
-----------------------------------------------------
Input
[
    [1,2,3,6,7],
    [2,4,3,2,1],
    [3,2,4,5,6],
    [6,5,6,5,4],
    [10,4,7,8,9],
    [12,4,9,8,7]
]
Output
1,2,3,6,10,12,4,9,8,7,9,4,6,1,7,6,3,2,4,2,5,4,7,8,5,5,2,3,4,6
Luis felipe De jesus Munoz
fonte
Então, estamos indo no sentido horário ou anti-horário?
LegionMammal978
@ LegionMammal978 anti-horário (I embora foi chamado anti-horário)
Luis Felipe de Jesus Munoz
7
Anti- e anti-horário estão corretos, sendo cada um mais comum em BrEng e AmEng, respectivamente. Se você realmente quer confundir, também pode usar o widdershins .
Digital Trauma

Respostas:

12

R , 54 bytes

Vários bytes salvos por @ Giuseppe e @ J.Doe.

f=function(m)if(ncol(m))c(m[,1],f(t(m[nrow(m):1,-1])))

Experimente online!

Retire recursivamente a primeira coluna e faça a reversão / transposição de linha (tornando a linha inferior a nova primeira coluna) o restante da matriz até você terminar com apenas uma coluna. Versão "tradicional" não destruída:

f <- function(m) {
 if(ncol(m) == 1) {
    m
  } else {
    c(m[,1], f(t(m[nrow(m):1,-1])))
  }
}

Foi apontado que ncol(m)poderia ser jogado para sum(m)salvar outro byte, porque podemos assumir valores positivos da matriz inteira. Mas vou deixar assim, pois funciona para todas as matrizes (mesmo matrizes de strings!)

ngm
fonte
Uau! Eu amo como o uso de t()impede o drop=TRUEpadrão `[`de estragar a ifcondição!
Giuseppe
e divulgação completa, eu tinha uma solução de 200 bytes que nem funcionava, então parabéns! Provavelmente vou conceder a você uma recompensa por isso assim que a pergunta for elegível para uma recompensa.
Giuseppe
@ Giuseppe voltar para 59 bytes! Fiquei agradavelmente surpreendido por t()não ter que usar um is.nullteste que estava nas minhas tentativas originais.
ngm
Essa última mnão será nula de qualquer maneira, para que você possa alterar a instrução if para 54 bytes . Parece funcionar para os casos de teste.
J.Doe
7

Pitão , 9 bytes

shMM.utC_

Experimente aqui!

Quão?

shMM.utC_     Full program. Takes a 2D array (matrix) from STDIN.
    .u        Until a result that has occurred before is found, loop and collect...
        _     Reverse the matrix (reverse the order of its rows).
       C      Transpose.
      t       Remove first element.
 hMM          For each element in the resulting 3D array, get the heads of its elements.
s             Flatten.
Mr. Xcoder
fonte
Isso é legal. Como Pyth iniciante eu agora sei que tenho muito a aprender,
ElPedro
5

Stax , 7 bytes

ôQÖG·í<

Execute e depure

Ele pega uma matriz de linhas em uma linha e produz saída separada por nova linha.

Descompactado, não jogado e comentado, é assim.

W       repeat the rest of the program until cancelled explicitly
  rM    rotate matrix *clock-wise* (yes, this is the opposite of the challenge)
  |c    assert matrix is truthy. (has rows) cancel otherwise.
  B     remove the top row of the matrix, and push separately to main stack
  rm    reverse the top row (this fixes the rotation direction), and print each value

Execute este

recursivo
fonte
4

Pitão, 20 bytes

J.TQWJ=+YhJ=J_.TtJ)Y

Experimente aqui

Explicação

J.TQWJ=+YhJ=J_.TtJ)Y
J.TQ                    Call the transposed input J.
    WJ            )     While J is not empty...
      =+YhJ             ... put the top row into Y (initially [])...
           =J   tJ      ... remove the top row...
             _.T        ... reverse and transpose (rotate clockwise).
                   Y    Output the result.

fonte
4

OK , 12 bytes

*+,/(1_+|:)\

Experimente online!

Isso abusa do fato de que oK parece não se importar muito com a forma da transposição. Em k isso seria 13 bytes : *:',/(1_+|:)\.

       +|:   /reverse, then transpose (rotate right)
     1_      /remove first line
    (     )\ /fixpoint of the above, keeping intermediate results (scan)
  ,/         /concatenate all the rows
*+           /get the first element of each row
zgrep
fonte
3

Limpo , 69 bytes

import StdEnv,StdLib
? =transpose
@[h:t]=h++ @(reverse(?t))
@_=[]

@o?

Experimente online!

Move a próxima linha / coluna para o início da lista, para que possa corresponder ao padrão no argumento.

Para o primeiro exemplo do desafio, isso se parece com:

@o? [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]
@ h=:[1, 5, 9, 13] t=:[[2, 6, 10, 14], [3, 7, 11, 15], [4, 8, 12, 16]]
[1, 5, 9, 13] ++ @ h=:[14, 15, 16] t=:[[10, 11, 12], [6, 7, 8], [2, 3, 4]]
[1, 6, 9, 13, 14, 15, 16] ++ @ h=:[12, 8, 4] t=:[[11, 7, 3], [10, 6, 2]]
[1, 6, 9, 13, 14, 15, 16, 12, 8, 4] ++ @ h=:[3, 2] t=:[[7, 6], [11, 10]]
[1, 6, 9, 13, 14, 15, 16, 12, 8, 4, 3, 2] ++ @ h=:[6, 10] t=:[[7, 11]]
[1, 6, 9, 13, 14, 15, 16, 12, 8, 4, 3, 2, 6, 10] ++ @ h=:[11, 7] t=:[]
[1, 6, 9, 13, 14, 15, 16, 12, 8, 4, 3, 2, 6, 10, 11, 7] ++ @ []
Furioso
fonte
3

Julia 0,7 , 47 bytes

f(m)=[m[:,1];sum(m)<1?[]:f(rotr90(m[:,2:end]))]

Experimente online!

Julia tem um conveniente embutido para girar a matriz em 90 graus, eliminando a necessidade de operações de transposição reversa.

Como você pode ver nos avisos do compilador, ele insiste em que todos os componentes da condicional ternária devem ser separados por espaços, e na v. 1.0 isso foi realmente aplicado.

Curiosamente, nessa situação, a maneira mais curta que encontrei para sair da recursão foi usar um bloco try-catch:

Julia 1.0 , 50 bytes

f(m)=[m[:,1];try f(rotr90(m[:,2:end]))catch;[]end]

Experimente online!

Kirill L.
fonte
2

JavaScript (Node.js) , 89 bytes

f=a=>a>[]?[...a.map(x=>x[0]),...f(a[0].map((_,i)=>a.map(y=>y[i]).reverse()).slice(1))]:[]

Experimente online!

Pega a primeira coluna, transpõe a restante e inverte cada linha (= gire a matriz 90 graus CW) e repita até que a matriz não tenha mais entradas.

Shieru Asakoto
fonte
2

APL (Dyalog) , 24 22 bytes

{×≢⍵:⍵[;1],∇⍉⊖0 1↓⍵⋄⍬}

Experimente online!

Quão?

{×≢⍵:⍵[;1],∇⍉⊖0 1↓⍵⋄⍬}
{                    } - a function
 ×≢⍵:                  - if non-empty:
     ⍵[;1]             - the left column
          ,∇⍉⊖0 1↓⍵    - repeat this function without the left column, rotated counter clockwise
                   ⋄⍬  - otherwise, return an empty vector
Zacharý
fonte
Uma explicação dos operadores seria legal.
precisa saber é o seguinte
1
@ Arc676, adicionado!
Zachary
2

05AB1E , 13 11 10 bytes

ΔRøćRˆ}¯˜þ

-2 bytes graças a @Emigna .

Experimente online ou verifique todos os casos de teste .

Explicação:

Δ         # Loop until the stack no longer changes:
 R        #  Reverse the order of the rows
          #   i.e. [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]]
          #    → [[13,14,15,16],[9,10,11,12],[5,6,7,8],[1,2,3,4]]
  ø       #  Zip, swapping rows and column
          #   → [[13,9,5,1],[14,10,6,2],[15,11,7,3],[16,12,8,4]]
   ć      #  Head extracted
          #   → [[14,10,6,2],[15,11,7,3],[16,12,8,4]] and [13,9,5,1]
    R     #  Reverse this row
          #   → [1,5,9,13]
     ˆ    #  Pop and push it to the global array
}         # After the loop:
 ¯        #  Push the global array
          #   i.e. [[1,5,9,13],[14,15,16],[12,8,4],[3,2],[6,10],[11],[7],"",""]
  ˜       #  Flatten it
          #   → [1,5,9,13,14,15,16,12,8,4,3,2,6,10,11,7,"",""]
   þ      #  Remove all empty string by only leaving all digits
          #   → ["1","5","9","13","14","15","16","12","8","4","3","2","6","10","11","7"]
          # (and output it implicitly)
Kevin Cruijssen
fonte
1

Carvão , 25 bytes

≔⮌EA⮌ιθWθ«≔E§θ⁰⮌Eθ§μλθI⊟θ

Experimente online! Link é a versão detalhada do código. Explicação:

≔⮌EA⮌ιθ

Gire a entrada em 180 °. Isso ocorre por dois motivos: a) a última linha é a mais fácil de remover eb) é mais fácil fazer um loop se a linha for removida no final do loop. (Tentei refletir e produzir no sentido horário, mas isso exigiu um byte extra.)

Wθ«

Repita até que a matriz esteja vazia.

≔E§θ⁰⮌Eθ§μλθ

Gire a matriz em 90 °.

I⊟θ

Remova a última linha da matriz e imprima o elemento como seqüências de caracteres em linhas separadas.

Neil
fonte
1

Ruby , 65 bytes

->a{x,*a=a.transpose;(w,*a=a.transpose.reverse;x+=w)while a[0];x}

Experimente online!

GB
fonte
1

PowerShell , 266 bytes

Sim. O PowerShell não é o melhor para lidar com matrizes. Mas, o algoritmo é basicamente o mesmo que o acima. Cada linha é representada como uma sequência separada por vírgula, e basicamente fazemos uma rotação e transposição para cada camada. Eu provavelmente pode raspar mais fora, mas ... Eu sou já de pijama ...

Filter F{$a=$_-replace"],|]|\s",''-split'\['|?{$_-ne''};$b=@();while($a-ne $null){$N=($a[0]-split',').Count-1;$a=0..$N|%{$i=$_;($a|%{($_-split',')[$i]})-join','};if($d){[array]::Reverse($a)}if($N-gt0){$b+=$a[0];$a=$a[1..$N]}else{$b+=$a;$a=$null};$d=$true}$b-join','}

Experimente online!

Jeff Freeman
fonte