Diamondize a Matrix

20

Dada uma matriz, produza uma representação da matriz onde o elemento superior esquerdo está no topo, a anti-diagonal é a linha central e o elemento inferior direito está na parte inferior.

Por exemplo, considere a seguinte matriz:

1 2 3
4 5 6
7 8 9

A versão em diamante desta matriz é:

  1
 4 2
7 5 3
 8 6
  9

Entradas e saídas

Uma matriz de entrada será fornecida como uma lista de listas (ou qualquer coisa semelhante no idioma de sua escolha). A saída também deve ser uma lista de listas.

As matrizes conterão apenas números inteiros positivos.

A matriz de entrada não será necessariamente quadrada.

A matriz de entrada será pelo menos 1 × 1.

Casos de teste

Input:  [[1]]
Output: [[1]]

Input:  [[1,2],[3,4]]
Output: [[1],[3,2],[4]]

Input:  [[1,2,3],[4,5,6]]
Output: [[1],[4,2],[5,3],[6]]

Input:  [[11,2,5],[3,99,3],[4,8,15],[16,23,42]]
Output: [[11],[3,2],[4,99,5],[16,8,3],[23,15],[42]]

Pontuação

Isso é , então a resposta mais curta em bytes vence.

Fatalizar
fonte
Relacionado
Fatalize 06/04
Relacionado / Generalização. (Será que não considera um ingênuo, porém, desde que se permitiu matrizes irregulares e exigiu rotação por qualquer múltiplo de 45 graus.)
Martin Ender
Relacionado.
Martin Ender

Respostas:

19

J, 7 bytes

<@|./.

Este é um verbo monádico sem nome que pega uma matriz e retorna uma lista de antidiagonais:

   input =. i.3 4
   input
0 1  2  3
4 5  6  7
8 9 10 11

   <@|./. input
┌─┬───┬─────┬─────┬────┬──┐
│0│4 1│8 5 2│9 6 3│10 7│11│
└─┴───┴─────┴─────┴────┴──┘

Teste aqui.

Explicação

  • /.é o J embutido para aplicar uma função a cada anti-diagonal. Infelizmente, essas anti-diagonais são dadas na ordem oposta ao que queremos aqui.
  • Em <@|., aplicamos primeiro o |.que inverte a anti-diagonal e depois <a caixa (que é a única maneira de retornar uma matriz irregular em J, pois as matrizes normais são sempre retangulares, portanto as antidiagonais seriam preenchidas com zeros).
Martin Ender
fonte
Isso é louco e bonito. Vou reservar um tempo para aprender esta língua algum dia.
máquina anseio
5

Python, 91 bytes

e=enumerate
lambda M:[[r[n-i]for i,r in e(M)if-1<n-i<len(r)][::-1]for n,_ in e(M[1:]+M[0])]

Teste em Ideone .


Python + NumPy, 69 bytes

import numpy
lambda M:map(M[::-1].diagonal,range(1-len(M),len(M[0])))

Espera uma matriz NumPy 2D como entrada e retorna uma lista de matrizes NumPy. Teste em Ideone .

Dennis
fonte
4

Geléia, 7 bytes

ṚŒDṙZL$

Experimente online!

Explicação

Ṛ         Reverse the matrix vertically.
 ŒD       Get its diagonals. However these start from 
          the main diagonal, not the corners.
    ZL$   Get the width of the input matrix.
   ṙ      Rotate the list of diagonals left by that many 
          places to obtain the correct order.
Martin Ender
fonte
Você não conhece o Jelly, mas isso não tem 7 bytes se requer operandos unicode.
Guidobot #
5
O @Guidobot Jelly usa uma página de código personalizada que codifica cada um dos 256 caracteres que entende como um único byte.
Dennis
4

Mathematica, 58 56 bytes

a=Length;Reverse@#~Diagonal~b~Table~{b,1-a@#,a@#&@@#-1}&

Função anônima, recebe matrizes aninhadas.

LegionMammal978
fonte
Você pode salvar um com Length[#]onde está \[Transpose]. E provavelmente outro de serrilhado Length.
SP3000
Ou Length@#&@@#para ASCII apenas na mesma contagem de bytes.
Martin Ender
3

CJam, 17 bytes

{eeSf.*::+W%zSf-}

Um bloco (função) sem nome que espera a matriz na pilha e a substitui por suas antidiagonais.

Teste aqui.

Isso (encontrado pelo Sp3000) funciona para a mesma contagem de bytes:

{_,,Sf*\.+W%zSf-}

Explicação

Isso é melhor explicado com um exemplo. Considere a entrada:

[[0  1  2  3]
 [4  5  6  7]
 [8  9 10 11]]

ee    e# Enumerate matrix, turning each row [x ... z] into [i [x ... z]] where
      e# i is the vertical index from the top.

[[0 [0  1  2  3]]
 [1 [4  5  6  7]]
 [2 [8  9 10 11]]]

Sf.*  e# Replace each i with a string of i spaces.

[[""   [0  1  2  3]]
 [" "  [4  5  6  7]]
 ["  " [8  9 10 11]]]

::+   e# Prepend these strings to the rows.

[[0  1  2  3]
 ['  4  5  6  7]
 ['  '  8  9 10 11]]   e# Note that each '  corresponds to a space character.

W%    e# Reverse the rows.

[['  '  8  9 10 11]
 ['  4  5  6  7]
 [0  1  2  3]]

z     e# Zip/transpose.

[[ '  '  0]
 [ '  4  1]
 [ 8  5  2]
 [ 9  6  3]
 [10  7]
 [11]]

Sf-   e# Remove spaces from each row.

[[ 0]
 [ 4  1]
 [ 8  5  2]
 [ 9  6  3]
 [10  7]
 [11]]
Martin Ender
fonte
3

Python 2, 88 87 bytes

lambda L:[filter(None,x)[::-1]for x in map(None,[],*[i*[0]+r for i,r in enumerate(L)])]

Coloque 0s, zip e remova os elementos falsos. Retorna uma lista de tuplas. Isso é usado map(None,...)para executar zip_longest (preenchimento de pontos ausentes None) efilter(None,...) remover elementos falsos.

Irritantemente, precisamos adicionar uma []linha extra ao mappara garantir que uma lista de tuplas seja retornada, pois map(None,*[[1]])retorna em [1]vez de [(1,)]para uma matriz 1x1. A linha extra é removida pelo filterpensamento.

(Obrigado a @Dennis por -1 byte)

Sp3000
fonte
3

Ruby, 68 66 bytes

Função anônima.

->l{i=-1;k=[];l.map{|r|i-=j=-1;r.map{|e|k[i+j+=1]=[e,*k[i+j]]}};k}
  • Por causa de como o operador splat funciona, pude salvar 2 bytes renunciando à adição da matriz.
Value Ink
fonte
2

Mathematica, 60 bytes

#&@@@#&/@GatherBy[Join@@MapIndexed[List,#,{2}],Tr@*Last]&

onde é um caractere Unicode que o Mathematica lê como o \[Transpose]operador postfix .

Isso é um pouco mais longo que a outra solução do Mathematica, mas achei que a postaria porque ela não usa o Diagonals built-in e usa uma abordagem completamente diferente.

Explicação

MapIndexed[List,#,{2}]

Isso primeiro transpõe a matriz (de modo que os antidiagonais apareçam na ordem correta se a matriz foi achatada). Em seguida, mapeamos Listas células da matriz junto com o índice, que transforma cada elemento da matriz iem {i, {x, y}}onde xe ysão as coordenadas do elemento na matriz.

Join@@...

Isso nivela a dimensão mais externa, para que agora tenhamos uma lista simples dos elementos da matriz (com suas coordenadas) na ordem principal da coluna.

GatherBy[..., Tr@*Last]

Isso agrupa esses elementos pela soma de suas coordenadas. Observe que antidiagonais são linhas de constante x+y, portanto, esse é exatamente o agrupamento que queremos. A ordem dentro de cada grupo é preservada. Agora só precisamos nos livrar das coordenadas novamente. Isso é feito através do um tanto enigmático:

#&@@@#&/@...

Isso mapeia a função #&@@@#&sobre cada grupo, que se aplica #& a cada elemento do grupo, e #é simplesmente o primeiro argumento, ou seja, o elemento da matriz original.

Martin Ender
fonte
Alguma explicação para o porquê é lida como \[transpose]?
Fatalize
1
@Fatalize É um ponto de código Unicode de uso privado, e o glifo que o Mathematica associa a este ponto de código é um sobrescrito T: reference.wolfram.com/language/ref/character/Transpose.html ... \[Transpose]é simplesmente a transliteração ASCII desse caractere Unicode. Copiar o caractere Unicode ou a transliteração para o Mathematica funcionará.
Martin Ender
2

Oitava, 77 bytes

Com um pouco de abuso da accumarrayfunção:

@(M)char(accumarray(((1:size(M,1))+(0:size(M,2)-1)')(:),M(:),[],@(x){num2str(x')}))

Isso define uma função anônima. Para usá-lo, atribua a uma variável ou useans .

Entrada é a matriz com :como separador de linhas. Saída é uma matriz de células que contém uma matriz para cada linha (a oitava é equivalente a matrizes irregulares). Isso é exibido pelo Octave, mostrando os índices da matriz de células e o conteúdo de cada célula. Experimente aqui .

Para exibir o resultado separado apenas por espaços e novas linhas: 83 bytes

@(M)char(accumarray(((1:size(M,1))+(0:size(M,2)-1)')(:),M(:),[],@(x){num2str(x')}))

Você também pode tentar aqui .

Luis Mendo
fonte
2

JavaScript (Firefox), 86 75 bytes

a=>a.concat(a[0]).slice(1).map((_,i)=>[for(v of a)if(n=v[i--])n].reverse())

Guardado 11 bytes graças a @Neil!

Funciona no Firefox 30+. Toma uma matriz de matrizes.

user81655
fonte
Bom algoritmo, mas você pode usar a.concat(a[0]).slice(1)para obter uma matriz do tamanho certo. Além disso, [for(of)]não é ES6; Eu normalmente escrevo como (Firefox 30+) ou algo assim.
611 Neil
@ Neil Wow, eu me sinto um pouco bobo por não querer usar concate slice. Obrigado!
user81655
2

Oitava, 63 62 bytes

Removido um byte graças a @DonMue ... @LuisMendo!

@(a)cellfun(@(x)x(x>0)',num2cell(spdiags(flipud(a)),1),'un',0)

Eu fui a rota chata e munged os antidiagonais.

Amostra executada em ideone .

taça
fonte
Eu acho que você pode encurtar 'uni'para'un'
Luis Mendo
@LuisMendo Por que sim, eu posso! Obrigado! :)
proveta
2

Haskell, 83 82 bytes

r=zip[0..]
\o->fst$span(any(>0))[reverse[e|(x,t)<-r o,(v,e)<-r t,x+v==a]|a<-[0..]]

nimi salvou um byte. Obrigado!

Lynn
fonte
1

Python, 128 bytes (numpy)

(lambda A: (lambda A,S:[[A[U][I-U] for U in range(min(S[1]-1,I),max(I-S[0]+1,0)-1,-1)] for I in range(S[1]+S[0]-1)])(A,A.shape))
Luis Masuelli
fonte
Bem-vindo à programação de quebra-cabeças e código de golfe! Por padrão, as submissões ao desafio de golfe código deve ser programas ou funções e uso de um dos métodos aprovados para I / O . Um trecho que espera a entrada em uma variável codificada permanentemente não é permitido.
Dennis
Parece que você pode refazer a primeira solução que usa lambdaem apenas um lambda que você pode usar como seu envio.
Alex A.
Vou Lambda-lo
Luis Masuelli
lambda A:[[A[U][I-U]for U in range(max(I-len(A)+1,0),min(len(A[0])-1,I)+1)]for I in range(len(A+A[0])-1)](como em sua revisão original) seria um pouco menor. Além disso, você deve mudar A[U][I-U]para A[I-U][U]obter orientação da questão.
Dennis
Vou verificar quando voltar para casa. Faz sentido
Luis Masuelli
1

Pitão , 41 17 bytes

tm_<dx+dYk.T+LaYk

Experimente online!

Inspirado na solução da @ Doorknob para outro problema .

Como funciona:

tm_<dx+dYk.T+LaYk
            +L      prepend to each subarray...
              aYk   (Y += ''). Y is initialized to [],
                    so this prepends [''] to the first
                    subarray, ['', ''] to the second, etc.
                    ['' 1  2  3
                     '' '' 4  5  6
                     '' '' '' 7  8  9
                     '' '' '' '' 10 11 12
                     '' '' '' '' '' 13 14 15]
          .T        transpose, giving us
                    ['' '' '' '' ''
                     1  '' '' '' ''
                     2  4  '' '' ''
                     3  5  7  '' ''
                     6  8  10 ''
                     9  11 13
                     12 14
                     15]
 m_<dx+dYk          removes all empty strings in the
                    subarrays while reversing each one
t                   remove the first subarray

Tentativa anterior:

JlQKlhQm_m@@Qk-dk}h.MZ,0-dtKh.mb,tJdUt+JK

Experimente online!

Como funciona:

JlQKlhQm_m@@Qk-dk}h.MZ,0-dtKh.mb,tJdUt+JK    input array stored as Q
JlQ                                          J = len(Q)
   KlhQ                                      K = len(Q[0])
       m                            Ut+JK    list for d from 0 to J+K-1:
        _m       }AAAAAAAAAABBBBBBBB             reversed list for k from A to B, where:
                  h.MZ,0-dtK                       A = max(0, d-(K-1))
                       0-dtK                               0  d-(K-1)
                            h.mb,tJd               B = min(J-1, d)
                                 tJd                       J-1  d
          @@Qk-dk                                    Q[k][d-k]
Freira Furada
fonte
1

Groovy, 77 73 75

{i->o=[].withDefault{[]};a=0;i.each{b=0;it.each{o[a+b++].add(0,it)};a++};o}

Pega a matriz de matrizes como entrada e retorna a matriz de matrizes.

Tente

EDIT: Eu esqueci de produzir a resposta, depois de adicioná-lo pontuação sobe para 75.

Krzysztof Atłasik
fonte