Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Inspired by Copied from this question at Stack Overflow.

Given a matrix A, create a matrix B such that the columns of A are arranged in a block-diagonal fashion. For example, given

1 2 3
4 5 6

the output would be

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

Rules

Input and output may be in the form of 2D arrays, nested arrays, or strings with different separators for rows and columns.

Numbers in the input (matrix A) will be positive integers.

Unary format is allowed, as long as zeros in the output are displayed in some reasonable way. For example, the above result could be displayed using quotation marks to enclose each number:

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

Test cases

Input, output:

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 10

 2  0
 6  0
10  0
 0  4
 0  8
 0 12
share|improve this question
    
Will all the numbers in A be different? – Adám Feb 25 at 1:46
    
@Nᴮᶻ No, they can be equal – Luis Mendo Feb 25 at 9:57

MATL, 6 bytes

"@N$Yd

Works in current version (13.0.0) of the language/compiler.

Input has the following form, with semicolon as row separator, and commas or spaces as column separators within each row:

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

Try it online!

Explanation

"         % 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

Worked example

Consider the input [1 2 3; 4 5 6]. The for loop beginning with " takes each column of the input. Within each iteration, @ pushes the current column onto the stack. So in the first iteration it pushes [1; 4]. N$ specifies that all the stack contents will be used as inputs of the following function, Yd.

This function (corresponding to MATLAB's blkdiag) "diagonally concatenates" its inputs to produce a block diagonal matrix (2D array). So in the first iteration Yd it takes one input and produces an output equal to that input, [1; 4], which is left on the stack.

In the second iteration the second column of the input, [2; 5], is pushed. Now Yd takes two 2×1 inputs, namely [1; 4] and [2; 5], and produces the 4×2 array [1 0; 4 0; 0 2; 0 5].

In the third iteration Yd takes the latter 4×2 array and the third column of the input, [3; 6], and produces the final result [1 0 0; 4 0 0; 0 2 0; 0 5 0; 0 0 3; 0 0 6].

share|improve this answer

ES6, 65 bytes

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

Takes as input and returns as output an array of arrays.

share|improve this answer
1  
@WashingtonGuedes The inner map returns a copy of the original 2D array with all but one column zeroed out. These copies then need to be concatenated, rather than just being elements of an outer 3D array. – Neil Feb 23 at 16:48

Mathematica, 40 39 Bytes

Credit to @Seeq for Infixing Flatten.

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

Input is a list of row vectors delimited by {} brackets. So the initial example is represented by

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

Generate an array of DiagonalMatrix where each one has diagonal elements from the rows of the input (3-D array). Transpose so the Flatten operation removes the correct bracket pairs to give the desired matrix (now 2-D array).

share|improve this answer
1  
Wouldn't DiagonalMatrix/@# work? And, by extension, Transpose[DiagonalMatrix/@#]~Flatten~1& – Seeq Feb 23 at 20:28
    
Good catch, I intended to fix that after rolling it up. Didn't think to use the Infix Flatten though. +1. – IPoiler Feb 23 at 21:49

Pyth, 17

s.em.>+dm0thQkbCQ

Try it online or run the Test Suite.

You can add a leading j to help visualize the 2D array.

share|improve this answer

Jelly, 13 bytes

ZLR’×L0ẋ;"Zz0

Try it online!

How it works

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.
share|improve this answer

Mathematica, 111 bytes

Join@@@ReplacePart[Table[0,#2/#3]~Table~#3~Table~#3,Table[{n,n}->#[[n]],{n,#3}]]&[Length@#,Length@Flatten@#,#]&
share|improve this answer
    
What's the input syntax? This throws Table and Part errors when using standard MMA matrix notation and results in an array of mixed dimensions. – IPoiler Feb 23 at 18:41

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

sigh Manually keeping track of the index is shorter than 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
share|improve this answer

R, 41 bytes

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

Assumes pryr, Matrix and plyr packages are installed.

This creates a function that takes a 2D array (a) and returns a "sparseMatrix" where (where 0's are represented as .)

(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

Explanation:

plyr::alply(a,2) each column of a and returns combines these results in a list

Matrix::.bdiag(lst) creates a block diagonal matrix from a list of matrices

pryr::f is a shorthand way to create a function.

A fully base R solution in 59 bytes (using the logic of @PieCot's Matlab answer):

function(a){l=dim(a);diag(l[2])%x%matrix(1,nrow=l[1])*c(a)}
share|improve this answer

MATLAB, 69 68 bytes

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

One byte was shaved off: thanks to Luis Mendo :)

share|improve this answer
    
You can save 1 byte replacing ones(r,1) by ~~(1:r)' – Luis Mendo Feb 23 at 22:22

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.