Matriz diagonal de bloques de columnas

16

Inspirado en Copiado de esta pregunta en Stack Overflow.

Dada una matriz A, cree una matriz de Bmodo que las columnas de Aestén dispuestas en forma de bloque diagonal. Por ejemplo, dado

1 2 3
4 5 6

la salida sería

1 0 0
4 0 0
0 2 0
0 5 0
0 0 3
0 0 6

Reglas

La entrada y la salida pueden estar en forma de matrices 2D, matrices anidadas o cadenas con diferentes separadores para filas y columnas.

Los números en la entrada (matriz A) serán enteros positivos.

Se permite el formato unario, siempre que los ceros en la salida se muestren de alguna manera razonable. Por ejemplo, el resultado anterior podría mostrarse entre comillas para encerrar cada número:

'1' '' ''
'1111' '' ''
'' '11' ''
'' '11111' ''
'' '' '111'
'' '' '111111'

Casos de prueba

De entrada y salida:

1 2 3
4 5 6

1 0 0
4 0 0
0 2 0
0 5 0
0 0 3
0 0 6


10 20

10  0
 0 20    


10
20

10
20


  1   2   3
 10  20  30
100 200 300

  1   0   0
 10   0   0
100   0   0
  0   2   0
  0  20   0
  0 200   0
  0   0   3
  0   0  30
  0   0 300

 2  4
 6  8
10 12

 2  0
 6  0
10  0
 0  4
 0  8
 0 12
Luis Mendo
fuente
¿Serán diferentes todos los números en A?
Adám
@ Nᴮᶻ No, pueden ser iguales
Luis Mendo

Respuestas:

7

MATL , 6 bytes

"@N$Yd

Funciona en la versión actual (13.0.0) del lenguaje / compilador.

La entrada tiene la siguiente forma, con punto y coma como separador de fila, y comas o espacios como separadores de columna dentro de cada fila:

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

Pruébalo en línea!

Explicación

"         % implicitly input 2D array and loop over its columns
  @       %   push column
  N$Yd    %   build block-diagonal matrix from all stack contents. Stack contents are
          %   a single column in the first iteration, or a partially built 2D array
          %   and a new column in all other iterations
          % end loop
          % implicit display

Ejemplo trabajado

Considere la entrada [1 2 3; 4 5 6]. El ciclo for que comienza con "toma cada columna de la entrada. Dentro de cada iteración, @empuja la columna actual a la pila. Entonces en la primera iteración empuja [1; 4]. N$especifica que todos los contenidos de la pila se utilizarán como entradas de la siguiente función Yd,.

Esta función (correspondiente a MATLAB blkdiag) "concatena diagonalmente" sus entradas para producir una matriz diagonal de bloque (matriz 2D). Entonces, en la primera iteración Yd, toma una entrada y produce una salida igual a esa entrada [1; 4], que se deja en la pila.

En la segunda iteración [2; 5], se empuja la segunda columna de la entrada ,. Ahora Ydtoma dos 2 × 1 entradas, a saber, [1; 4]y [2; 5], y produce la matriz 4 × 2 [1 0; 4 0; 0 2; 0 5].

En la tercera iteración Ydtoma la última matriz 4 × 2 y la tercera columna de la entrada [3; 6], y produce el resultado final [1 0 0; 4 0 0; 0 2 0; 0 5 0; 0 0 3; 0 0 6].

Luis Mendo
fuente
3

ES6, 65 bytes

a=>[].concat(...a[0].map((_,i)=>a.map(b=>b.map((c,j)=>i-j?0:c))))

Toma como entrada y devuelve como salida una matriz de matrices.

Neil
fuente
1
@WashingtonGuedes El mapa interno devuelve una copia de la matriz 2D original con todas las columnas excepto una puesta a cero. Estas copias deben ser concatenadas, en lugar de ser simplemente elementos de una matriz 3D externa.
Neil
3

Mathematica, 40 39 Bytes

Crédito a @Seeq por Infixing Flatten.

Transpose[DiagonalMatrix/@#]~Flatten~1&

La entrada es una lista de vectores de fila delimitados por {}paréntesis. Entonces el ejemplo inicial está representado por

{{1,2,3},{4,5,6}}

Genere una matriz de DiagonalMatrixdonde cada uno tiene elementos diagonales de las filas de la entrada (matriz 3D). TransposePor lo tanto, la Flattenoperación elimina los pares de paréntesis correctos para obtener la matriz deseada (ahora matriz 2D).

IPoiler
fuente
1
No DiagonalMatrix/@#funcionaria? Y, por extensión,Transpose[DiagonalMatrix/@#]~Flatten~1&
seequ
Buena captura, tenía la intención de arreglar eso después de enrollarlo. Infix FlattenAunque no pensé en usar el . +1.
IPoiler
1

Jalea, 13 bytes

ZLR’×L0ẋ;"Zz0

Pruébalo en línea!

Cómo funciona

ZLR’×L0ẋ;"Zz0  Main link. Input: M (matrix)

Z              Transpose M.
 L             Get the length of the result. This yields the number of M's columns.
  R            Range; for m columns, yield [1, ..., m].
   ’           Decrement to yield [0, ..., m-1].
    ×L         Multiply each by the length (number of rows) of M.
               This yields [0, n, ..., n(m-1)], where n is the number of rows.
      0ẋ       Push a list of lists of zeroes.
               First element is [], last is n(m-1) zeroes.
        ;"Z    Prepend the kth vector of zeroes to the kth column of M.
           z0  Zip, filling the non-rectangular 2D array with zeroes.
Dennis
fuente
1

Mathematica, 111 bytes

Join@@@ReplacePart[Table[0,#2/#3]~Table~#3~Table~#3,Table[{n,n}->#[[n]],{n,#3}]]&[Length@#,Length@Flatten@#,#]&
CalculadoraFeline
fuente
¿Cuál es la sintaxis de entrada? Esto arroja Tabley Parterrores al usar notación y matriz de resultados MMA estándar en una variedad de dimensiones mixtas.
IPoiler
1

Ruby, 81 78 76 62 bytes

->a{i=-1;a[0].flat_map{i+=1;a.map{|b|x=b.map{0};x[i]=b[i];x}}}

suspiro Hacer un seguimiento manual del índice es más corto que with_index.

->a{
i=-1;            # index of the flat_map
a[0]             # duplicate all rows as many times as necessary
.flat_map{       # we're wrapping each "group" of original rows with yet another
                 #  array, so we need to flat_map to get rid of those
i+=1;            # increment the index of the current subarray
a.map{|b|        # for each sub-subarray (these are the rows)...
x=b.map{0};      # zero everything out
x[i]=b[i];       # replace the desired elements
x}}}             # finally, return the modified array
Pomo de la puerta
fuente
1

R, 41 bytes

pryr::f(Matrix::.bdiag(plyr::alply(a,2)))

Asume pryr, Matrixy los plyrpaquetes están instalados.

Esto crea una función que toma una matriz 2D (a) y devuelve una "matriz dispersa" donde (donde los 0 se representan como .)

(a=matrix(1:6,ncol=3))
#      [,1] [,2] [,3]
# [1,]    1    3    5
# [2,]    2    4    6
pryr::f(Matrix::.bdiag(plyr::alply(a,2)))(a)
# 6 x 3 sparse Matrix of class "dgTMatrix"
#          
# [1,] 1 . .
# [2,] 2 . .
# [3,] . 3 .
# [4,] . 4 .
# [5,] . . 5
# [6,] . . 6

Explicación:

plyr::alply(a,2)cada columna de ay retornos combina estos resultados en una lista

Matrix::.bdiag(lst) crea una matriz diagonal de bloque a partir de una lista de matrices

pryr::f es una forma abreviada de crear una función.

Una Rsolución completamente base en 59 bytes (usando la lógica de la respuesta de Matlab de @ PieCot):

function(a){l=dim(a);diag(l[2])%x%matrix(1,nrow=l[1])*c(a)}
mnel
fuente
1

MATLAB, 69 68 bytes

   function h=d(a)
   [r,c]=size(a);h=repmat(a,c,1).*kron(eye(c),~~(1:r)')

Se eliminó un byte: gracias a Luis Mendo :)

PieCot
fuente