创建N维单形(四面体)


12

一个可以为任何尺寸创建的最简单的N维形状是Simplex,这是一组N + 1个点,它们彼此之间的距离相等。

对于2维,这是等边三角形,对于3维,这是正则四面体,在4维上是5单元,依此类推。

挑战

给定整数维N作为输入,输出代表该维单纯形的数组/列表/堆栈/ N个维点中的任意一个。即,N + 1个顶点彼此相等且距离不为零。

Lua中的参考实施

例子

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...]]

笔记

  • 输入是任何标准格式的数字,并且始终是大于1且小于10的整数
  • 硬编码允许输入1,但不能更高。
  • 输出中允许出现合理的错误。浮点算术或Trig问题可能会被忽略。
  • N维单纯形的任何变换都是允许的,只要它保持正则和非零即可。
  • 禁止使用标准漏洞
  • 这是,因此最少的字节获胜。

1
您意识到不能强迫答案不进行硬编码吗?避免这种情况的最简单方法是增加输入范围。同样“有效的标准必须是客观的”,合理的不是客观的。
user202729

看起来这可以通过采用单位矩阵加一个条目都相等的额​​外矢量来解决。
xnor

@xnor做到了;)
PattuX

Answers:


4

果冻,11 字节

‘½‘÷ẋW
=þ;Ç

在线尝试!

通过产生作品同一性矩阵的大小Ñ并用通过重复生成的列表串联它Ñ的单倍√(N + 1)+ 1,除以Ñ

‘½‘÷ẋ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.

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

=þ;Ç   – Main link.

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

5

Python 78 66字节

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

当然可以改善,尤其是在处理n = 1`''时。(哪怕是一个单纯形符号也是如此?)只需意识到这是没有必要的。还是可以改善的^^

在线尝试!

[i*[0]+[1]+(n+~i)*[0]for i in range(n)]创建身份矩阵。所有点之间都有距离sqrt(2)。(感谢Rod的改进)

现在,我们需要n+1第-点与所有其他点的距离相同。我们必须选择(x, x, ... x)

从远处(1, 0, ... )(x, x, ... x)sqrt((x-1)²+x²+...+x²)。如果我们想要一个n维单纯形,结果将是sqrt((x-1)²+(n-1)x²),因为我们在第一点有一个1n-1 0。简化一下:sqrt(x²-2x+1+(n-1)x²) = sqrt(nx²-2x+1)

我们希望这个距离是sqrt(2)

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

解决这个二次方程式(一个解决方案,另一个解决方案也很好):

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

将其n放入列表中,将该列表放入列表中,然后与身份矩阵合并。


-4字节感谢Alex Varga:

将每个向量乘以n。这会将单位矩阵的创建更改为lambda n:[i*[0]+[n]+(n+~i)*[0](相同长度),并消除n了附加点的除法,因此它变得n*[1+(n+1)**.5]节省了两个方括号和/n


尽管不在这个挑战的范围之内,但是0维单纯形也是一件很可怕的事情。
ATaco

多读一点之后,难道不是每对不同的数字都是1单数吗?
PattuX '18年

是的,这就是单纯形的令人讨厌的力量
ATaco

1
您可以更改生成标识矩阵以节省8个字节的方式
Rod Rod

1
66个字节,结合先前的注释
Alex Varga,


2

APL(Dyalog)20 18字节

1字节感谢@ngn

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

在线尝试!


(∘.=⍨⍳)->∘.=⍨∘⍳
ngn

@ngn我一直在打高尔夫球,我一直在等我看高尔夫之前是否能打更多的字节,因为使用移动设备编辑帖子真的很痛苦
Uriel

我可以自由地为您编辑它。我也怀疑可能会有更好的答案-这让我想起了,但我不太明白它是如何工作的……
ngn

矩阵除法无效,但我发现了一个有趣的循环函数:{÷¯1+4○⍵*.5}⍪⍳∘.=⍳
ngn

@ngn谢谢。我使用了您的解决方案的默认版本进行同样的计数
Uriel 18'Jan

1

JavaScript(ES7),70个字节

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

@PattuX的Python答案的端口。


1

Wolfram语言(Mathematica),205个字节

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

Mathematica中的单纯形函数从开始{0,0,...]},{1,0,0,...]},在原点放置第一个点,在x轴上放置第二个点,在x,y平面上放置第三个点,在x,y,z空间上放置第四个点等。此过程将重用所有先前的点,并在新维度中一次添加一个新点

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

验证

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}

1
欢迎光临本站!1)这是代码高尔夫球,您应力争使代码尽可能短。2)请使用Markdown使您的帖子更具可读性。
Caird coinheringaahing


0

Ruby,55个字节

而不是针对所有维度返回相似的幅度,而是使用公式(1+(n+1)**0.5)/nI按比例放大n以简化公式,从而得出(1+(n+1)**0.5)

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

在线尝试!

在测试程序中取消

一个lambda函数,将其n作为参数并返回一个数组数组。

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

输出

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


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.