Create an N-Dimensional Simplex (Tetrahedron)

The Simplest N-Dimensional shape one can create for any dimension is a Simplex, and this is a set of N+1 points that are all equal distance away from eachother.

For 2 dimensions, this is an equilateral triangle, for 3 dimensions, this is an regular tetrahedron, at 4 dimensions is the 5-Cell and so on.

The Challenge

Given an Integer dimension N as input, output an Array/List/Stack/Whatever of N Dimensional points that represent a Simplex of this dimension. That is, N+1 vertexes that are equal and non-zero distance from eachother.

Reference implementation in Lua

Examples

1 -> [[0], [1]]
2 -> [[0, 0], [1, 0], [0.5, 0.866...]]
4 -> [[0, 0, 0, 0], [1, 0, 0, 0], [0.5, 0.866..., 0, 0], [0.5, 0.288..., 0.816..., 0], [0.5, 0.288..., 0.204..., 0.790...]]


Notes

• Input is a number in any standard format, and will always be an integer greater than 1 and less than 10
• Hardcoding is allowed for input of 1, but nothing higher.
• Reasonable error is allowed in the output. Issues with floating point arithmetic or trig may be ignored.
• Any transformation of the N dimensional simplex is allowed, aslong as it remains Regular and Non-zero.
• Standard Loopholes are forbidden.
• This is , so fewest bytes wins.
• You realize that you can't force answers to not hardcode? The simplest way to avoid that is to increase the range of input. Also "valid criteria must be objective", reasonable is not objective. – user202729 Jan 8 '18 at 4:21
• It looks like this can be solved by taking the identity matrix plus one extra vector whose entries are all equal. – xnor Jan 8 '18 at 4:29
• @xnor done that ;) – PattuX Jan 8 '18 at 4:32

Jelly, 11 bytes

‘½‘÷ẋW
=þ;Ç


Try it online!

Works by generating the identity matrix of size N and concatenating it with the list generated by repeating N times the singleton √(N + 1) + 1, divided by N.

‘½‘÷ẋW – Helper link (monadic). I'll call the argument N.

‘      – Increment N (N + 1).
½     – Square root.
‘    – Increment (√(N + 1) + 1).
÷   – Divide by N.
ẋ  – Repeat this singleton list N times.
W – And wrap that into another list.

––––––––––––––––––––––––––––––––––––––––––

=þ     – Outer product of equality.
;Ç   – Concatenate with the result given by the helper link applied to the input.


Python 78 66 Bytes

lambda n:[i*[0]+[n]+(n+~i)*[0]for i in range(n)]+[n*[1+(n+1)**.5]]


Surely can be improved, especially at handling n=1. (How is that even a simplex?) Just realized that's not necessary. Can probably be improved still ^^

Try it online!

[i*[0]+[1]+(n+~i)*[0]for i in range(n)] creates identity matrix. All points have distance sqrt(2) from each other. (thanks to Rod for improving)

Now we need a n+1-th point with the same distance to all other points. We have to choose (x, x, ... x).

Distance from (1, 0, ... ) to (x, x, ... x) is sqrt((x-1)²+x²+...+x²). If we want an n dimensional simplex this turns out to be sqrt((x-1)²+(n-1)x²), as we have one 1 and n-1 0s in the first point. Simplify a bit: sqrt(x²-2x+1+(n-1)x²) = sqrt(nx²-2x+1)

We want this distance to be sqrt(2).

sqrt(2) = sqrt(nx²-2x+1)
2 = nx²-2x+1
0 = nx²-2x-1
0 = x²-2/n*x+1/n

Solving this quadratic equation (one solution, other one works fine, too):

x = 1/n+sqrt(1/n²+1/n) = 1/n+sqrt((n+1)/n²) = 1/n+sqrt(n+1)/n = (1+sqrt(n+1))/n

Put that in a list n times, put that list in a list and join with identity matrix.

-4 Bytes thanks to Alex Varga:

Multiply each vector by n. This changes the creation of the identity matrix to lambda n:[i*[0]+[n]+(n+~i)*[0] (same length) and gets rid of the division by n in the additional point, so it becomes n*[1+(n+1)**.5], saving two brackets and the /n.

• Although not in the scope of this challenge, 0 dimensional simplexes are also a thing, as horrible as that may sound. – ATaco Jan 8 '18 at 3:56
• After reading a bit more, isn't every pair of different numbers a 1-simplex? – PattuX Jan 8 '18 at 4:21
• Yep, such is the annoying power of simplexes – ATaco Jan 8 '18 at 5:56
• You can change to way to generate the identity matrix to save 8 bytes – Rod Jan 8 '18 at 11:51
• 66 bytes combining previous comments – Alex Varga Jan 10 '18 at 16:45

Wolfram Language (Mathematica), 46 bytes

IdentityMatrix@#~Join~{Table[1-(#+1)^.5,#]/#}&


Try it online!

APL (Dyalog), 20 18 bytes

1 byte thanks to @ngn

∘.=⍨∘⍳⍪1÷¯1+4○*∘.5


Try it online!

• (∘.=⍨⍳) -> ∘.=⍨∘⍳ – ngn Jan 8 '18 at 17:30
• @ngn I have this golf on stand by, I was waiting to see if I can golf some more bytes before I put this in because editing posts is really pain using mobile – Uriel Jan 8 '18 at 18:15
• I took the liberty to edit it for you. I too suspect there might be a better answer - it reminds me of ⌹ but I can't quite figure out how it could work... – ngn Jan 8 '18 at 19:30
• matrix division was fruitless but I found an interesting circular function: {÷¯1+4○⍵*.5}⍪⍳∘.=⍳ – ngn Jan 9 '18 at 20:41
• @ngn thanks. I used a tacit version of your solution for the same count – Uriel Jan 10 '18 at 13:03

JavaScript (ES7), 70 bytes

n=>[a=Array(n++).fill((1+n**.5)/--n),...a.map((_,i)=>a.map(_=>+!i--))]


Wolfram Language (Mathematica), 205 bytes

f1 = Sqrt[# (# + 1)/2]/# /(# + 1) & ;
f2 = Sqrt[# (# + 1)/2]/# & ;
simplex[k_] := {ConstantArray[0, k]}~Join~Table[
Table[f1[n], {n, 1, n - 1}]~Join~{f2[n]}~Join~
ConstantArray[0, k - n],
{n, k}]


Simplex function in Mathematica Starting from {0,0,...]},{1,0,0,...]}, Placing first point at origin, Second point on x axis Third point in x,y plane, Fourth point in x,y,z space, etc. This progression reuses all the previous points, adding one new point at a time in new dimension

simplex[6]={{0, 0, 0, 0, 0, 0}, {1, 0, 0, 0, 0, 0}, {1/2, Sqrt[3]/2, 0, 0, 0,
0}, {1/2, 1/(2 Sqrt[3]), Sqrt[2/3], 0, 0, 0}, {1/2, 1/(2 Sqrt[3]),
1/(2 Sqrt[6]), Sqrt[5/2]/2, 0, 0}, {1/2, 1/(2 Sqrt[3]), 1/(
2 Sqrt[6]), 1/(2 Sqrt[10]), Sqrt[3/5], 0}, {1/2, 1/(2 Sqrt[3]), 1/(
2 Sqrt[6]), 1/(2 Sqrt[10]), 1/(2 Sqrt[15]), Sqrt[7/3]/2}}


Verification

In[64]:= EuclideanDistance[simplex[10][[#[[1]]]],simplex[10][[#[[2]]]]] & /@ Permutations[Range[10],{2}]//Simplify
Out[64]= {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}

• Welcome to the site! 1) This is a code golf, you should aim to make your code as short as possible. 2) Please use Markdown to make your post as readable as possible. – caird coinheringaahing Jan 8 '18 at 16:25

Octave, 31 bytes

Saved 2 bytes thanks to Luis Mendo.

@(n)[n*eye(n);~~(1:n)+(n+1)^.5]


Try it online!

• You can replace ones(1,n) by ~~(1:n) – Luis Mendo Jan 10 '18 at 11:47

Ruby, 55 bytes

rather than returning similar magnitudes for all dimensions and using the formula (1+(n+1)**0.5)/n I scale up by a factor of n to simplify the formula to (1+(n+1)**0.5)

->n{(a=[n]+[0]*~-n).map{a=a.rotate}+[[1+(n+1)**0.5]*n]}


Try it online!

ungolfed in test program

A lambda function taking n as an argument and returning an array of arrays.

f=->n{
(a=[n]+[0]*~-n).map{        #setup an array a containing n and n-1 zeros. perform n iterations (which happens to be the the size of the array.)
a=a.rotate}+                #in each iteration rotate a and return an array of all possible rotations of array a
[[1+(n+1)**0.5]*n]          #concatenate an array of n copies of 1+(n+1)**0.5
}

p f[3]                        # call for n=3 and print output


output

[[0, 0, 3], [0, 3, 0], [3, 0, 0], [3.0, 3.0, 3.0]]


Pari/GP, 37 bytes

n->concat((n+1)^.5-matid(n),1^[1..n])


Try it online!

R, 38 bytes

function(n)rbind(diag(n,n),1+(n+1)^.5)
`

Try it online!