N-dimensional identity "matrix"

30

2

Given a positive integer n, output the N-dimensional identity "matrix", which is the N^N array with 1 where all the components of the indices are equal and 0 otherwise. N^N means N-by-N-by-N-by-...

1 -> [1]

2 -> [[1,0],[0,1]]

3 -> [[[1,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,1,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,1]]]

4 -> [[[[1,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]],[[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],[[0,0,0,0],[0,1,0,0],[0,0,0,0],[0,0,0,0]],[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]],[[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],[[0,0,0,0],[0,0,0,0],[0,0,1,0],[0,0,0,0]],[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]],[[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,1]]]]

For example, if a is the 4-dimensional identity "matrix", then the only entries with 1 would be a[0][0][0][0], a[1][1][1][1], a[2][2][2][2], and a[3][3][3][3].

This is . Shortest answer in bytes wins. Standard loopholes apply.

Leaky Nun

Posted 2017-06-22T17:02:00.963

Reputation: 45 011

1Related, related. – Leaky Nun – 2017-06-22T17:02:11.707

11Here comes the MATL answer with a builtin doing it for you... – caird coinheringaahing – 2017-06-22T18:47:32.217

Answers

16

Octave, 29 bytes

@(n)accumarray((x=1:n)'+!x,1)

Try it online!

rahnema1

Posted 2017-06-22T17:02:00.963

Reputation: 5 435

9

Jelly, 8 bytes

×=¥þ’¡`Ṡ

Try it online!

Ooh, looks like I get to outgolf @Dennis in his own language again :-)

This is a 1-argument function (because Jelly's default output format for nested lists is a little ambiguous, meaning that it arguably doesn't fulfil the spec as a full program).

Explanation

×=¥þ’¡`Ṡ
     ¡    Repeatedly apply the following operation,
    ’     {input-1} times in total:
   þ        For each element of the current value {perhaps made into a range}
      `     and of {the range from 1 to the} {input}:
 =            Compare corresponding elements, giving 0 for equal or 1 for unequal
× ¥           then multiply by one of the elements
       Ṡ  then replace each element with its sign

In order to understand this, it helps to look at the intermediate steps. For an input of 3, we get the following intermediate steps:

  1. [1,2,3] (input, made into a range implicitly by the þ)
  2. [[1,0,0],[0,2,0],[0,0,3]] (make a table with [1,2,3], compare for equality to get [[1,0,0],[0,1,0],[0,0,1]], then multiply by one of the values we compared)
  3. [[[1,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,2,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,3]]] (the same idea again)
  4. [[[1,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,1,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,1]]] (replace each element with its sign using )

Note the fact that the input starts out 1-dimensional means that we have to loop (input-1) times in order to add (input-1) dimensions, producing an input-dimensional list.

Fun fact: this program contains five quicks in a row, ¥þ’¡`. (A quick is a modifier to a "link", or builtin, used to modify its behaviour or combine it with another link.)

user62131

Posted 2017-06-22T17:02:00.963

Reputation:

+!, just because you beat Dennis in Jelly. – Zacharý – 2017-06-23T12:42:29.910

7

Mathematica, 30 bytes

Array[Boole@*Equal,#~Table~#]&

ngenisis

Posted 2017-06-22T17:02:00.963

Reputation: 4 600

1

@FryAmTheEggman an integer parameter as the second argument to Table is a recent addition. Mathics still needs a singleton list there: https://tio.run/##y00sychMLv7/P83WsagosTLaKT8/J9VBy7WwNDFHR7kuJDEpJ7WuWrk2Vo0roCgzryQ6Ldo4Nvb/fwA

– Martin Ender – 2017-06-22T17:43:50.047

1@FryAmTheEggman Looks like you need to change it to Array[Boole@*Equal,#~Table~{#}]& to work on Mathics. Older versions of Mathematica don't support an integer as the second argument to Table, and I guess Mathics is based off that. – ngenisis – 2017-06-22T17:44:45.563

1@MartinEnder Pinch, poke, you owe me a Coke :) – ngenisis – 2017-06-22T17:46:10.843

6

APL (Dyalog), 10 bytes

1=≢∘∪¨⍳⍴⍨⎕

Try it online!

1= [is] 1 equal to

 the number

 of

 unique elements

¨ in each of

 the indices in an array with the dimensions of

⍴⍨ the self-reshape (N copies of N) of

 the input (N) [?]

Adám

Posted 2017-06-22T17:02:00.963

Reputation: 37 779

5

Jelly, 9 bytes

ðṗE€ṁ+þ’¡

Try it online!

How it works

Achieving the task directly seems to be difficult (I haven't found a way), but contructing arrays of the same numbers and arrays of the same shape is quite easy.

ð makes the chain dyadic, and the integer input n serves as both left and right argument for the chain. It's possible to use a monadic chain instead, but the parsing rules for dyadic ones save three bytes here (two after accouting for ð).

The Cartesian power atom , with left and right argument equal to n, constructs the array of all vectors of length n that consist of elements of [1, ..., n], sorted lexicographically.

When n = 3, this yields

[[1, 1, 1], [1, 1, 2], [1, 1, 3], [1, 2, 1], [1, 2, 2], [1, 2, 3], [1, 3, 1], [1, 3, 2], [1, 3, 3], [2, 1, 1], [2, 1, 2], [2, 1, 3], [2, 2, 1], [2, 2, 2], [2, 2, 3], [2, 3, 1], [2, 3, 2], [2, 3, 3], [3, 1, 1], [3, 1, 2], [3, 1, 3], [3, 2, 1], [3, 2, 2], [3, 2, 3], [3, 3, 1], [3, 3, 2], [3, 3, 3]]

The equal each quicklink E€ tests the elements of all constructed vectors for equality.

When n = 3, we get

[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]

which are the elements of the 3-dimensional identity matrix, in a flat array.

The dyadic quicklink +þ’¡ is called with left argument and right argument n. The quick ¡ calls the decrement atom , which yields n-1, then calls the add table quicklink n-1 times.

Initially, the arguments of are both n. After each call, the right argument is replaced by the left one, and the left one is replaced by the return value of the call.

The table quick calls the add atom + for each elements of its left argument and each element of its right argument, constructing a table/matrix of the return value. The initial integer arguments n are promoted to the ranges [1, ... n].

When n = 3, after promotion but before the first iteration, both arguments are

[1, 2, 3]

Adding each integer in this array to each integer in this array yields

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

In the next invocation, we add each of these arrays to the integers in [1, 2, 3]. Addition vectorizes (adding an integer to an array adds it to each element), so we get

[[[3, 4, 5], [4, 5, 6], [5, 6, 7]],
 [[4, 5, 6], [5, 6, 7], [6, 7, 8]],
 [[5, 6, 7], [6, 7, 8], [7, 8, 9]]]

This array has the same shape as the 3-dimensional identity matrix, but not the correct elements.

Finally, the mold atom discards the integer entries of the result to the right and replaces them in order with the elements in the result to the left.

Dennis

Posted 2017-06-22T17:02:00.963

Reputation: 196 637

4

Python, 70 bytes

f=lambda n,l=[]:[f(n,l+[i])for i in(len(l)<n)*range(n)]or+(l==l[:1]*n)

Try it online!

A recursive solution. Thinking of the matrix as a list of matrices one dimension smaller, it iterates over that list to go down the tree. It remembers the indices picked in l, and when n indices have been picked, we assign a 1 or 0 depending on whether they are all the same.


Python 2, 73 bytes

n=input();r=0
exec'r=eval(`[r]*n`);'*n+('n-=1;r'+'[n]'*n+'=1;')*n
print r

Try it online!

An improvement on totallyhuman's method of making a matrix of zeroes and then assigning ones to the diagonal.


Python 2, 88 bytes

n=input()
t=tuple(range(n))
print eval('['*n+'+(i0'+'==i%d'*n%t+')'+'for i%d in t]'*n%t)

Try it online!

Some nonsense with eval, generating a nested list, and string-format substitution. The string to be evaluated looks like:

[[[+(i0==i0==i1==i2)for i0 in t]for i1 in t]for i2 in t]

xnor

Posted 2017-06-22T17:02:00.963

Reputation: 115 687

4

Python 2 + NumPy, 80 72 70 bytes

Now tied with the top Python answer!

from numpy import*
n=input()
a=zeros((n,)*n)
a[[range(n)]*n]=1
print a

Try it online

Saved 8 bytes thanks to Andras Deak, and 2 by officialaimm

mbomb007

Posted 2017-06-22T17:02:00.963

Reputation: 21 944

2Make use of fancy indexing: a[[range(n)]*n]=1 instead of your exec. – Andras Deak – 2017-06-22T23:06:12.613

(There's actually fill_diagonal(a,1) for this purpose, but that's one byte longer) – Andras Deak – 2017-06-23T00:59:53.023

1+1 for the pretty output. And, I don't see the use of the variable i, that should save 2 bytes. – officialaimm – 2017-06-23T04:44:46.417

3

Python 2, 99 93 90 bytes

Thanks to Rod for some even more help that got it working and also shaved 6 bytes off! -3 bytes thanks to xnor.

n=input()
r=eval(`eval('['*n+'0'+']*n'*n)`)
for i in range(n):exec'r'+`[i]`*n+'=1'
print r

Try it online!

totallyhuman

Posted 2017-06-22T17:02:00.963

Reputation: 15 378

1def/return is never better than input/print (in the best scenario it's equal), you can also drop the () in ('[%d]'%i) reducing to 93 bytes – Rod – 2017-06-22T18:14:37.240

1'[%d]'%i happens to be the string rep of [i]. – xnor – 2017-06-22T18:17:06.443

2

JavaScript (ES6), 67 bytes

f=(n,d=n-1,i)=>[...Array(n)].map((_,j)=>d?f(n,d-1,j-i?n:j):j-i?0:1)

Explanation: i is used to keep track of whether the cell is on the main diagonal or not. Initially it's undefined, so on the first recursive call we always pass the first dimension, while on subsequent recursive calls we only pass it on if the current dimension index is equal to all previous dimensions, otherwise we pass an index of n which indicates that all of the recursive cells should be zero.

Neil

Posted 2017-06-22T17:02:00.963

Reputation: 95 035

2

R, 64 49 bytes

-15 bytes thanks to Jarko Dubbeldam

x=array(0,rep(n<-scan(),n));x[seq(1,n^n,l=n)]=1;x

Reads from stdin and returns an array, printing as matrices. seq generates a sequence evenly spaced from 1 to n^n with length l=n, which does the trick quite nicely to index where the 1s go.

Try it online!

old version:

n=scan();x=rep(0,n^n);x=array(x,rep(n,n));x[matrix(1:n,n,n)]=1;x

Reads n from stdin; returns an array, printing the results as matrices. I struggled with this for a while until I read the docs for [, which indicate that a matrix can be used to index an array, where each row of the matrix represents the set of indices. Neat!

Try it online!

Giuseppe

Posted 2017-06-22T17:02:00.963

Reputation: 21 077

array(0, rep(n,n) works, so you dont have to do rep. You can then also take n through array(0, rep(n<-scan(),n)). – JAD – 2017-06-22T20:11:35.530

Also, x[seq(1,n^n,l=n)]=1 is 1 byte shorter. – JAD – 2017-06-22T20:16:48.273

@JarkoDubbeldam thank you! Nice one. – Giuseppe – 2017-06-23T13:03:11.767

2

Brainfuck, 61 bytes

>,[->+>+<<]>[-<<+>>]>-[->+.-<<<<[->+>+<<]>[-<+>]>[->>.<<]>]+.

Ungolfed

The numbers after the angle brackets indicate the cell the head is over.

>,                   read n to 1
[->+>+<<]            move 1 to 2 and 3
>2[-<<+>>]>3         move 2 to 0 
                     (tape: n 0 0 n 0)
-[                   while cell 3 {
    -                  dec 3
    >4+.-<3            print \x1
    <<<0[->+>+<<]      move 0 to 1 and 2
    >1[-<+>]>2         move 1 to 0
                       (tape: 0 0 n rows_left 0)
    [                  while cell 2 {
        -                dec 2
        >>4.<<           print \x0
    ]>3                }
]                    }
+.                   print \x1

Try it online!

Input is a binary number. Output is a matrix stored in row-major order.

Ray

Posted 2017-06-22T17:02:00.963

Reputation: 1 488

There are a few different output formats in the answers already, so I'm assuming that the only requirement is "some standard matrix representation". If it needs to be in a particular format, I'll modify the code accordingly. – Ray – 2017-06-22T22:28:31.823

i guess row-major in this particular case would look exactly like column-major – Octopus – 2017-06-23T05:50:07.957

@Octopus Actually, the program determines whether it should be in row-major or column-major order based on the language the Brainfuck interpreter is written in. Mine is written in C, so it naturally outputs the matrix in row-major order. However, if you used an interpreter written in Fortran or MATLAB, it would detect that and automatically switch to column major order. (If you used an interpreter written in Brainfuck itself, it resolves the ambiguity based on the language your text editor is written in.) :-) – Ray – 2017-06-23T08:59:01.073

1

J, 16 15 bytes

i.@#~=i.*]#.#&1

Try it online!

miles

Posted 2017-06-22T17:02:00.963

Reputation: 15 654

1

Common Lisp, 147 133 bytes

(defun i(n)(flet((m(x)(fill(make-list n)x)))(let((a(make-array(m n):initial-element 0)))(dotimes(i n)(incf(apply #'aref a(m i))))a)))

Try it online!

The usual super-lengthy lisp. Reduced 12 bytes thank to @ceilingcat!

Explanation:

(defun i (n)
  (flet ((m (x) (fill (make-list n) x)))            ; function to build a list of n values x
    (let ((a (make-array (m n) :initial-element 0))); build the array with all 0
      (dotimes (i n)                                ; for i from 0 to n-1
        (incf (apply #'aref a (m i))))              ; add 1 to a[i]..[i] 
      a)))                                          ; return the array

Renzo

Posted 2017-06-22T17:02:00.963

Reputation: 2 260

@ceilingcat, ops, there was a stupid error in the golfed version. Corrected, thanks! – Renzo – 2017-07-11T05:10:28.290

1

Python 3 + numpy, 81 77 bytes

from numpy import*
f=lambda n:all([a==range(n)for a in indices((n,)*n)],0)+0

I'm not entirely sure that the above fits all guidelines: it returns an ndarray with the given properties. I know anonymous functions are usually fine, but an interactive shell will actually print

>>> f(2)
array([[1, 0],
       [0, 1]])

If the array fluff makes the above invalid, I have to throw in a print() for something like 7 additional bytes.

Try it online!

Andras Deak

Posted 2017-06-22T17:02:00.963

Reputation: 203

1

Pyth, 14 bytes

ucGQtQms!t{d^U

Test suite

Explanation: ^U, which is implicitly ^UQQ, where Q is the input, calculates all possible Q element lists of the range 0 ... n-1. ms!t{d maps the ones with all elements equal to 1, and the rest to 0. This gives the flattened output

ucGQtQ executes the following, Q - 1 times: Chop the input into lists of size Q.

isaacg

Posted 2017-06-22T17:02:00.963

Reputation: 39 268

1

C# (.NET Core), 166 bytes

n=>{var c=new int[n];int i=0,d;for(;i<n;c[i++]=n);var m=System.Array.CreateInstance(typeof(int),c);for(i=0;i<n;i++){for(d=0;d<n;c[d++]=i);m.SetValue(1,c);};return m;}

Try it online!

At first I thought it could not be done with a lambda expression in C#... ^__^U

Charlie

Posted 2017-06-22T17:02:00.963

Reputation: 11 448

0

SOGL V0.12, 22 bytes

.^κ.H/ 0* 1.H≤Οčr.H{.n

Try it Here!
Leaves the output on the stack, viewable in the console. If the numbers in the output were allowed to be strings, then the r could be removed.
Just as a fun test of how SOGL does in challenges it was completely not made for :p

input: x
.^                      push  x^x
  κ                     subtract x    (x^x)-x
   .H/                  divide by x   ((x^x) - x)/x
       0*               get that many zeroes
          1             push "1"
           .H           push x-1
             ≤          pull the first item from the stack to the top
              Ο         encase (x-1 times the zeroes, separated, started and ended with 1s)
               č        chop to a char-array
                r       convert each character to a number
                 .H{    repeat x-1 times:
                    .n    in the top array, for each group of x contents, encase that in an array

dzaima

Posted 2017-06-22T17:02:00.963

Reputation: 19 048

0

Clojure, 92 bytes

#(reduce(fn[v i](assoc-in v(repeat % i)1))(nth(iterate(fn[v](vec(repeat % v)))0)%)(range %))

Nice that assoc-in works also with vectors, not only with hash-maps.

NikoNyrh

Posted 2017-06-22T17:02:00.963

Reputation: 2 361