24
\$\begingroup\$

Diagonalize a vector into a matrix.

Input

A vector, list, array, etc. of integers \$\mathbf{v}\$ of length \$n\$.

Output

A \$n \times n\$ matrix, 2D array, etc. \$A\$ such that for each element \$a_i \in \mathbf{v}\$,

$$ A = \left( \begin{array}{ccc} a_1 & 0 & \cdots & 0 \\ 0 & a_2 & \cdots & 0 \\ \vdots & \vdots & \ddots & \vdots \\ 0 & 0 & \cdots & a_n \end{array} \right) $$

where the diagonal of \$A\$ is each element in \$\mathbf{v}\$.

Notes

  • This is , so shortest program or function in bytes wins!
  • Construct the Identity Matrix may be of use to you.
  • If the length of \$\mathbf{v}\$ is 0, you may return an empty vector, or an empty matrix.
  • If the length of \$\mathbf{v}\$ is 1, you must return a \$1 \times 1\$ matrix.

Not Bonus

You can receive this Not Bonus if your program is generic across any type, using the type's zero-value (if it exists) in place of \$0\$.

Test Cases

[] -> []
[0] -> [[0]]
[1] -> [[1]]
[1, 2, 3] -> [[1, 0, 0], [0, 2, 0], [0, 0, 3]]
[1, 0, 2, 3] -> [[1, 0, 0, 0], [0, 0, 0, 0], [0, 0, 2, 0], [0, 0, 0, 3]]
[1, -9, 1, 3, 4, -4, -5, 6, 9, -10] -> [[1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, -9, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 3, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 4, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, -4, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, -5, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 6, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 9, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, -10]]
\$\endgroup\$
1
  • 3
    \$\begingroup\$ Suggested test case: a vector containing 0 \$\endgroup\$ Commented Jul 14, 2023 at 16:43

40 Answers 40

11
\$\begingroup\$

K (ngn/k), 7 bytes

{x*=#x}

My first K post. I tried real hard to make a Bubbler train work here but failed.

Try it online!

\$\endgroup\$
2
  • 2
    \$\begingroup\$ Nice! I think the bubbler train version is possible but likely longer. I came up with: */(=#:)\ \$\endgroup\$
    – coltim
    Commented Jul 16, 2023 at 18:34
  • \$\begingroup\$ Ah, that looks cool, very nice. I am hoping my next K solution will be less trivial :P \$\endgroup\$
    – south
    Commented Jul 16, 2023 at 21:20
8
\$\begingroup\$

Haskell, 39 bytes

f[]=[];f(a:b)=(a:map(0*)b):map(0:)(f b)

Recursively generates the matrix by appending a value at the top left corner of a smaller matrix.

\$\endgroup\$
6
\$\begingroup\$

MATL, 2 bytes

Xd

The code uses the builtin function Xd (which corresponds to MATLAB's diag). Try it online!

\$\endgroup\$
5
\$\begingroup\$

Jelly, 5 bytes

J=þ`a

Try it online!

J=þ`     Identity matrix:
  þ      table
J        [1 .. length]
   `     with itself
 =       by equality.
    a    Vectorizing logical AND; replace ones with elements of the vector.

If output can be flat:

Jelly, 3 bytes

jn`

Try it online!

j      Join the vector on
 n     the list of, for each element, if it doesn't equal
  `    itself.

If the empty vector didn't have to be handled, this could tie non-flat as jn`sL; it passes all current test cases as owing to all inputs being nonzero (which is not guaranteed by the spec).

\$\endgroup\$
5
\$\begingroup\$

Octave, 4 bytes

diag

Try it online!

Python, 23 bytes

from numpy import*
diag

Attempt This Online!

\$\endgroup\$
0
5
\$\begingroup\$

Go, 135 130 bytes

func(v[]int)(A[][]int){for i,_:=range v{r:=make([]int,len(v))
for j,_:=range v{e:=0
if i==j{e=v[i]}
r[j]=e}
A=append(A,r)}
return}

Attempt This Online!

Go, 141 136 bytes + Not Bonus

func f[T any](v[]T)(A[][]T){for i,_:=range v{r:=make([]T,len(v))
for j,_:=range v{var e T
if i==j{e=v[i]}
r[j]=e}
A=append(A,r)}
return}

Attempt This Online!

\$\endgroup\$
5
\$\begingroup\$

Haskell, 34 bytes

foldr(\a m->(a:(0<$m)):map(0:)m)[]

Try it online!

Uses the recursive method from Magma of expanding the matrix with a new value in the top left, but with foldr and <$.

\$\endgroup\$
5
\$\begingroup\$

Nekomata, 6 bytes

x:ᵒ-¬*

Attempt This Online!

Multiplies the identity matrix like other answers.

x:ᵒ-¬*
x       [0 .. length - 1]
 :      Duplicate
  ᵒ     Outer product with
   -        Subtract
    ¬   Logical NOT
     *  Multiply
\$\endgroup\$
4
\$\begingroup\$

J, 6 bytes

*[:=#\

Try it online!

\$\endgroup\$
4
\$\begingroup\$

Thunno 2, 5 bytes

ėDȷ=×

Try it online!

Inspired by Unrelated String's Jelly answer.

Explanation

ėDȷ=×  # Implicit input
ė      # Length range
 D     # Duplicate
  ȷ    # Outer product over:
   =   #  Check for equality
    ×  # Multiply by the input
       # Implicit output
\$\endgroup\$
4
\$\begingroup\$

Haskell, 67 bytes

f v=m.(m.).h where m g=map g[0..length v-1];h z i j|i==j=v!!i|1>0=z

Attempt This Online!

\$\endgroup\$
4
\$\begingroup\$

Python, 56 55 bytes

-1 byte thanks to xnor

def f(a,i=0):
 for b in a:l=a[i]=[0]*len(a);l[i]=b;i+=1

Attempt This Online!

Outputs by modifying arguments.

\$\endgroup\$
1
  • \$\begingroup\$ -1 byte \$\endgroup\$
    – xnor
    Commented Jul 16, 2023 at 3:20
4
\$\begingroup\$

TypeScript's Type System, 62 bytes

type F<V>={[I in keyof V]:{[J in keyof V]:J extends I?V[J]:0}}

Try it at the TypeScript Playground!

It's been a little while since I've golfed in TS types, so it's possible (though I think unlikely) that I missed a shorter way to do this. This one is pretty simple, but I'll leave an explanation anyway:

type F<V> =           // type F taking generic tuple type V
  { [I in keyof V]:   // for each I in V's indices:
    { [J in keyof V]: //   for each J in V's indices:
      J extends I     //     are J and I the same type?
        ? V[J]        //       if so, index into V with J
        : 0           //       otherwise, 0
    }                 //   end
  }                   // end

I tried putting keyof V into type F<V,K=keyof V> but that doesn't work since the compiler complains that K could be a type unrelated to an array key, and it doesn't save enough bytes for //ts-ignore to be worth it.

\$\endgroup\$
4
\$\begingroup\$

Dyalog APL, 9 bytes

Thanks to @att for -4

⊢×⍤1⍋∘.=⍋­⁡​‎‎⁡⁠⁡‏‏​⁡⁠⁡‌⁢​‎‎⁡⁠⁢‏⁠‎⁡⁠⁣‏⁠‎⁡⁠⁤‏‏​⁡⁠⁡‌⁣​‎‎⁡⁠⁢⁡‏⁠‎⁡⁠⁢⁢‏⁠‎⁡⁠⁢⁣‏⁠‎⁡⁠⁢⁤‏⁠‎⁡⁠⁣⁡‏‏​⁡⁠⁡‌­
⊢          # ‎⁡v
 ×⍤1       # ‎⁢multiplied row-wise with
    ⍋∘.=⍋  # ‎⁣the identity matrix of size (#v)

💎 Created with the help of Luminespire

Dyalog APL, 16 bytes + Not Bonus

The only other applicable scalar type are characters, where APL uses the space as the empty character, so this code also does

,⍨∘≢⍴∊⍤(⊢↑¨⍨1+≢)­⁡‎‎⁡⁠⁢⁡‏‏⁡⁠⁡‌⁢‎‎⁡⁠⁡‏⁠‎⁡⁠⁢‏⁠‎⁡⁠⁣‏⁠‎⁡⁠⁤‏⁠‏⁡⁠⁡‌⁣‎‎⁡⁠⁢⁢‏⁠‎⁡⁠⁢⁣‏‏⁡⁠⁡‌⁤‎‎⁡⁠⁣⁡‏⁠‎⁡⁠⁣⁣‏‏⁡⁠⁡‌⁢⁡‎‎⁡⁠⁣⁢‏⁠‎⁡⁠⁣⁤‏‏⁡⁠⁡‌⁢⁢‎‎⁡⁠⁤⁡‏⁠‎⁡⁠⁤⁢‏⁠‎⁡⁠⁤⁣‏‏⁡⁠⁡‌­
    ⍴             # ‎⁡Reshape
,⍨∘≢              # ‎⁢to (#v)*(#v) matrix 
     ∊⍤           # ‎⁣the flattened list of lists built by
        ⊢ ¨       # ‎⁤taking each item of v
         ↑ ⍨      # ‎⁢⁡and padding it with
            1+≢   # ‎⁢⁢(#v) zeros
💎

Created with the help of Luminespire

This works by noticing that, if the diagonalized matrix is read as a single list, row by row, each entry of v is spaced with as many zeros as the length of v.

\$\endgroup\$
3
  • \$\begingroup\$ 9 on the first: ⊢×⍤1⍋∘.=⍋ \$\endgroup\$
    – att
    Commented Jul 14, 2023 at 20:12
  • \$\begingroup\$ @att nice solution, will add! \$\endgroup\$
    – RubenVerg
    Commented Jul 14, 2023 at 20:34
  • \$\begingroup\$ @att I somehow forgot about the Rank operator, was struggling for a while to get vec × matrix to work \$\endgroup\$
    – RubenVerg
    Commented Jul 14, 2023 at 20:37
3
\$\begingroup\$

PARI/GP, 11 bytes

matdiagonal

Builtins are always a sad answer, aren't they?

\$\endgroup\$
3
\$\begingroup\$

Factor + math.matrices, 15 bytes

diagonal-matrix

Try it online!

\$\endgroup\$
3
\$\begingroup\$

APL(Dyalog Unicode), 9 bytes SBCS

-∘⍳⍤≢↑⍤0⊢

Try it on APLgolf!

Left-pads each \$v_i\$ to a vector of length \$i\$ and implicitly mixes.

Each row's fill elements match the type of the corresponding element of the vector.

\$\endgroup\$
3
\$\begingroup\$

JavaScript (Node.js), 34 bytes

x=>x.map((v,i)=>x.map(_=>i--?0:v))

Try it online!

\$\endgroup\$
3
\$\begingroup\$

Mathematica, 14 bytes

Try it online!

DiagonalMatrix
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Does it work for empty vector? I tried passing {}, but got an error, but maybe I'm doing something wrong? (I don't speak Mathematica well) \$\endgroup\$
    – pajonk
    Commented Jul 15, 2023 at 18:04
3
\$\begingroup\$

Excel, 33 bytes

=IFERROR(MUNIT(ROWS(A1#))*A1#,"")

Excel, 39 bytes + Not Bonus

=IFERROR(IF(MUNIT(ROWS(A1#)),A1#,0),"")

Input is vertical spilled range A1#.

Having to deal with the empty vector is inconvenient; otherwise these would be just 21 and 27 bytes respectively.

\$\endgroup\$
3
\$\begingroup\$

Itr, 9 bytes

#äLºµÍ·®£

prints the elements of the matrix separated by spaces, with , separating the rows. Does not print the zero entries above the diagonal.

online interpreter

Explanation

#          ; read array from standard input
 äLº       ; push the range from zero to array.length-1
    µÍ     ; replace each element in the range with a vector having a one at the given index
           ; this will give an identity matrix of size array.length represented as 2D array 
      ·    ; point-wise multiplication
       ®   ; convert result to matrix
        £  ; print

Itr, 10 9 bytes

#äLºµÍ·®+£ (broken in current version)

#LºµÍ·®+£

Adds zero to the result to force the entries above the diagonal to be printed.


Itr, 8 bytes

#LºµÍ·®£

the ä before the L is no longer necessary in newer versions

\$\endgroup\$
2
\$\begingroup\$

R, 20 bytes

\(x)diag(x,sum(x|1))

Attempt This Online!

The diag built-in almost works here, but fails for inputs of length 1, where it produces identity matrix of size of the input. Unless specified nrow argument.


Less boring - without diag built-in:

R, 54 bytes

\(x,`[`=matrix)c(x,rep(0*x,n<-sum(x|1)))[n+1,n,T][n,n]

Attempt This Online!

Idea: construct a vector such that every entry of the input \$x\$ of length \$n\$ is followed by \$n\$ zeros. A matrix with \$x\$ in the first row and followed by \$n\$ rows of zeros works too. Then, we can put this in a \$n\times n\$ matrix resulting in \$x\$ on the diagonal.

Ungolfed:

\(x){n=length(x)
m=matrix(c(x,rep(0,n^2)), nrow=n+1, ncol=n, byrow=TRUE)
matrix(m, nrow=n, ncol=n)}

R, 27 bytes

\(v,x=seq(a=v))v*!x%o%x-x^2

Attempt This Online!

Heavily inspired by @Kirill L.'s answer to the linked challenge.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ You could also do diag(sum(x|1))*x \$\endgroup\$
    – Giuseppe
    Commented Oct 12, 2023 at 20:26
  • \$\begingroup\$ @Giuseppe you're right, but it's less obvious why it works ;) \$\endgroup\$
    – pajonk
    Commented Oct 13, 2023 at 5:04
2
\$\begingroup\$

Python, 23 bytes

import numpy
numpy.diag

Attempt This Online!

\$\endgroup\$
2
  • \$\begingroup\$ I tried with [['a'],['b'],['c']], and it gives just ['a'] as the output. \$\endgroup\$
    – bigyihsuan
    Commented Jul 14, 2023 at 18:43
  • \$\begingroup\$ Oh oops, it doesn't seem to work for lists :(. It works for numbers and strings though. \$\endgroup\$
    – The Thonnu
    Commented Jul 14, 2023 at 18:53
2
\$\begingroup\$

Vyxal, 25 bitsv2, 3.125 bytes

LÞ□*

Try it Online!

The P flag on the permalink is to make the test cases pass (for some strange reason, I never made it not check exact string representation.) Individual cases all produce the right output with vyxal list syntax without the flag.

Explained

LÞ□*­⁡​‎‎⁡⁠⁡‏‏​⁡⁠⁡‌⁢​‎‎⁡⁠⁢‏⁠‎⁡⁠⁣‏‏​⁡⁠⁡‌⁣​‎‎⁡⁠⁤‏‏​⁡⁠⁡‌­
L     # ‎⁡Push the length of the input
 Þ□   # ‎⁢Construct an NxN identity matrix
   *  # ‎⁣and pair-wise vectorise multiplication
💎

Created with the help of Luminespire.

\$\endgroup\$
2
\$\begingroup\$

Rust, 83 81 bytes

Simple and dirty imperative solution.

-2 bytes by taking a slice instead of a vec

|v:&[i8]|{let l=v.len();let mut r=vec![vec![0;l];l];for i in 0..l{r[i][i]=v[i]}r}

Try it online!

Rust, 126 124 bytes + Not Bonus

The Copy bound is technically too strict and a Clone bound would be enough, but it would also be one byte longer :shrug:.

fn f<T:Default+Copy>(v:&[T])->Vec<Vec<T>>{let l=v.len();let mut r=vec![vec![T::default();l];l];for i in 0..l{r[i][i]=v[i]}r}

Try it online!

\$\endgroup\$
2
\$\begingroup\$

><> (Fish), 53 bytes

l::0)?\;
$:@:?v\
1-21.\:&{:}0l5-&=?$n~9o
~1-10.\~{~ao

Hover over any symbol to see what it does

Try it

\$\endgroup\$
2
  • 1
    \$\begingroup\$ ahhh that's a lotta broken images lol \$\endgroup\$
    – bigyihsuan
    Commented Jul 16, 2023 at 20:42
  • 3
    \$\begingroup\$ This is a very cool but strange way to explain a program lol \$\endgroup\$
    – south
    Commented Jul 16, 2023 at 21:19
2
\$\begingroup\$

Pip -P, 6 bytes

g*EY#g

(The flag is only necessary to format the output in a readable way; any of -P, -p, -S will do.)

Attempt This Online!

Explanation

g*EY#g
     g  ; List of command-line arguments
    #   ; Length
  EY    ; Identity matrix of that size
g*      ; Multiply each row by the corresponding element of g
\$\endgroup\$
2
\$\begingroup\$

Uiua, 7 6 bytes

×⊞=.⍏.

-1 thanks to Bubbler

Try it!

×⊞=.⍏.
     .  # duplicate
 ⊞=.⍏   # identity matrix
×       # multiply
\$\endgroup\$
4
  • \$\begingroup\$ I think you need an extra ⇡⧻ or similar to cope with [1 2 1 2].... \$\endgroup\$ Commented Oct 12, 2023 at 22:14
  • \$\begingroup\$ @DominicvanEssen Thanks, fixed. \$\endgroup\$
    – chunes
    Commented Oct 12, 2023 at 22:24
  • \$\begingroup\$ You can get a vector of unique elements in 1 byte using , which saves a byte over ⇡⧻. \$\endgroup\$
    – Bubbler
    Commented Oct 13, 2023 at 2:34
  • \$\begingroup\$ @Bubbler Cool. Thanks! \$\endgroup\$
    – chunes
    Commented Oct 13, 2023 at 2:42
1
\$\begingroup\$

Python, 66 bytes

def f(a):n=range(len(a));return[[(i==j)*a[i]for i in n]for j in n]

Attempt This Online!

Python, 66 bytes

def f(a):x=len(a);return[[0]*i+[a[i]]+[0]*(x+~i)for i in range(x)]

This solution was inspired by this answer.

Attempt This Online!

\$\endgroup\$
2
  • \$\begingroup\$ 61 bytes \$\endgroup\$
    – Ethan C
    Commented Jul 14, 2023 at 17:33
  • \$\begingroup\$ @EthanC 56 bytes \$\endgroup\$ Commented Jul 15, 2023 at 10:52
1
\$\begingroup\$

Charcoal, 11 bytes + Not Bonus

⭆¹EθEθ×⁼μξν

Try it online! Link is to verbose version of code. Explanation:

   θ        Input array
  E         Map over elements
     θ      Input array
    E       Map over elements
        μ   Row index
       ⁼    Equals
         ξ  Column index
      ×     Multiplied by
          ν Inner element
⭆¹          Pretty-print

Using And instead of Times would have made the code minusculely more efficient but this way the code produces empty strings on the non-diagonal entries when given a string array as input.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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