打印立方体的顶点及其覆盖的三角形


9

输出立方体顶点的坐标。然后,输出将覆盖该多维数据集的十二个三角形的列表,每个三角形是三个顶点索引(一致定向)的列表。输出必须是不同十进制数字的ASCII字符串。该高尔夫没有输入。优胜者是最少的字符,其中的字符集是Unicode。

例如,考虑一个1x1x1立方体,角为0,0,0。多维数据集的八个顶点可以通过3d笛卡尔网格上的以下xyz坐标来描述:

x y z = (0,0,1) (1,0,1) (1,1,1) (0,1,1) (0,0,0) (1,0,0) (1,1,0) (0,1,0)

可以给每个顶点一个索引: x y z->index: 0 0 1->0, 1 0 1->1, 1 1 1->2, 0 1 1->3, 0 0 0->4, 1 0 0->5, 1 1 0->6, 0 1 0->7

现在考虑顶面,索引为零到三的顶点。两个覆盖三角形可以用三个索引分别描述:

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

这是从立方体上方看的这张顶面的图片:

 3_____2
 |    /| 
 |   / |                  
 |  /  |
 | /   |
 0_____1                

这是一个角度的视图。

    3____2
   / __-/|
 0/_`__1 |
  |    | /6
  |____|/
 4     5

请注意,当从立方体的“外部”直接看待讨论的面时,这两个三角形的方向或“缠绕”是“逆时针”(想象访问列出的每个顶点,逆时针旋转)。现在,想象对多维数据集的所有六个面都执行此操作。

vertices: (0,0,1) (1,0,1) (1,1,1) (0,1,1) (0,0,0) (1,0,0) (1,1,0) (0,1,0)
triangles as indices: [0,1,2], [2,3,0], [6,5,4], [4,7,6], 
  [5,2,1], [2,5,6], [0,3,4], [4,3,7], [2,6,3], [3,6,7], [0,4,1], [1,4,5]

您可以输出位于任意坐标处的任意大小的多维数据集。您可以根据需要编号和排序顶点坐标。索引可以基于0或基于1。从多维数据集外部观察时,三角形的方向可以是顺时针或逆时针,只要它对所有三角形都一致即可。

只要每个ASCII十进制数字都至少由一个非数字ASCII字符分隔,就可以按需要设置输出的格式。例如,上面的示例也可以如下输出:

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

该高尔夫的灵感来自各种3d图形系统和格式,包括OpenGL,OBJ,OFF,AMF,CGAL等。该高尔夫类似于Calvin's Hobbies的名为“在数字立方体上输出一个面孔”的高尔夫,这是您需要的大差异自己输出顶点的xyz坐标并输出三角形索引。谢谢阅读。

每个用户的灵感都来自python2(非高尔夫)中的“帮助程序”验证程序,该程序将在变量vertstr和idxstr中为测试输出数据打印“ ok”或“ not ok”。它不能完美运行...但是会捕获一些错误。

编辑:修复示例中的错字和验证代码中的错误。

    

#vertstr ='0 0 0 0 0 1 0 1 0 0 1 1 1 0 0 1 0 1 1 1 0 1 1 1'
#idxstr ='1 2 0 2 1 3 7 5 6 4 6 5 2 4 0 4 2 6 7 3 5 1 5 3 4 1 0 1 4 5 7 6 3 2 3 6'
vertstr ='0 0 1 1 0 1 1 1 1 0 1 1 0 0 0 0 0 0 1 1 0 0 1 0'
idxstr ='0 1 2 2 3 0 6 5 4 4 7 6 5 2 1 2 5 6 0 3 4 4 3 7 2 6 3 3 6 7 0 4 1 1 4 5'

类向量:
    def __init __(self,v):
        self.x,self.y,self.z = v [0],v [1],v [2]
    def __add __(self,v):
        返回向量([self.x + vx,self.y + vy,self.z + vz])
    def __sub __(self,v):
        返回向量([self.xv.x,self.yv.y,self.zv.z])
    def __str __():
        返回str(self.x)+','+ str(self.y)+','+ str(self.z)

def cross(v1,v2):
    x = v1.y * v2.z-v2.y * v1.z
    z = v1.x * v2.y-v2.x * v1.y
    y = v1.z * v2.x-v2.z * v1.x
    返回向量([x,y,z])

#http://mathforum.org/library/drmath/view/55343.html&http://sympy.org
def绕组(v1,v2,v3,obs):
    x1,y1,z1,x2,y2,z2,x3,y3,z3,x4,y4,z4 = v1.x,v1.y,v1.z,v2.x,v2.y,v2.z,v3。 x,v3.y,v3.z,obs.x,obs.y,obs.z
    d = x1 *(y2 * z3-y2 * z4-y3 * z2 + y3 * z4 + y4 * z2-y4 * z3) 
    d = d + y1 *(-x2 * z3 + x2 * z4 + x3 * z2-x3 * z4-x4 * z2 + x4 * z3) 
    d = d + z1 *(x2 * y3-x2 * y4-x3 * y2 + x3 * y4 + x4 * y2-x4 * y3)
    d = d-x2 * y3 * z4 + x2 * y4 * z3 + x3 * y2 * z4-x3 * y4 * z2-x4 * y2 * z3 + x4 * y3 * z2 
    返回d

def法线(v1,v2,v3):
    va = v2-v1
    vb = v3-v2
    vc = v1-v3
    n1 =交叉(va,vb)
    n2 =交叉(vb,vc)
    n3 =跨(vc,va)
    返回[n1,n2,n3]


def triplify(str):
    nums,triples = [],[]
    对于str.split('')中的num:nums + = [int(num)]
    对于范围(0,len(nums),3)中的i:
        三元组+ = [[nums [i],nums [i + 1],nums [i + 2]]]
    返回三元组

顶点= Triplify(顶点)
指数=三倍化(idxstr)
nsum =向量([0,0,0])
windsum = 0
xs,ys,zs = [],[],[]
对于v而言:
    xs + = [v [0]]
    ys + = [v [1]]
    zs + = [v [2]]
#print xs,ys,zs,len(xs)
center = Vector([float(sum(xs))/ len(xs),float(sum(ys))/ len(ys),float(sum(zs))/ len(zs)])
对于索引中的三角形:
    v1 =向量(verts [triangle [0]])
    v2 =向量(verts [triangle [1]])
    v3 =向量(verts [triangle [2]])
    规范=法线(v1,v2,v3)
    打印v1,v2,v3,规范[0],规范[1],规范[2]
    对于n的规范:
        nsum + = n
    w =绕组(v1,v2,v3,中心)
    打印'winding',w
    如果w <0:windsum- = 1
    小数w> 0:windsum + = 1
如果abs(windsum)== 12:打印'winding ok'
否则:打印“绕线不正常”
if(nsum.x == 0且nsum.y == 0且nsum.z == 0):打印'normal sum ok'
否则:打印“正常金额不正确”

1
从示例中可以清楚地看到,但是仅为了使其完全明确,您可能要提到索引是从0开始的。这不是给定的,因为您列出的示例格式(OBJ)中至少有一种格式使用基于1的索引。
Reto Koradi 2015年

那也将起作用。我认为此挑战的一个困难是,验证输出的正确性会有些痛苦。您几乎必须在纸上绘制具有所选顶点顺序的多维数据集,然后手动验证所有12个三角形。好吧,您可以编写一个验证程序。那实际上可能是另一种挑战性的想法……我认为比这更困难。
Reto Koradi

我真的很喜欢另一个高尔夫验证者的想法。我更新了示例以提供完整的数据集。再次感谢。
唐明亮

好的,我添加了一个非常快速且肮脏的验证程序,该程序对每个三角形中每对向量的叉积进行求和,并将它们全部相加,如果0表示“确定”。
2015年

Answers:


1

Pyth,18个字符

j`CM"⭧勛囃勦⾽仵ᶌﻘꚱ쥎➡˻ì

与我的Haskell回答相同的想法;印刷品:

[
1
1
1
1
1
,

2
1
2
1
1
...

我爱您在3种不同的语言中使用了相同的unicode字符串
Don

1
这是什么Unicode魔术?
RK。

2

CJam,35个字节

YZm*`3{[XY4]m<)\0+_:+1$f-+_@f+W%}%`

在线尝试

输出为:

[[0 0 0] [0 0 1] [0 1 0] [0 1 1] [1 0 0] [1 0 1] [1 1 0] [1 1 1]] [[1 2 0 2 1 3 ] [7 5 6 4 6 5] [2 4 0 4 2 6] [7 3 5 1 5 3] [4 1 0 1 4 5] [7 6 3 2 3 6]

三角形的方向是从外部顺时针旋转。我手动检查了一下,对我来说看起来是正确的。

说明:

YZ      Push 2 and 3 on stack.
m*      Cartesian power, creates the coordinates of the 8 vertices.
`       Convert to string for output. Done with vertices.
3{      Start loop over 3 coordinate directions.
  [XY4]   Push [1 2 4], which are the vertex index offsets for the 3 directions.
  m<      Rotate by loop counter. So the remaining loop body will be executed once
          with [1 2 4], once with [2 4 1], once with [4 1 2].
  )       Pop off last offset. Will use this as index offset between the two
          parallel faces.
  \       Swap pair of remaining two offsets to top. These are the index offsets
          within the face.
  0+      Add a 0 to the list. These 3 indices define the first triangle.
  _:+     Calculate the sum. This is the vertex index of the opposite corner.
  1$      Copy first triangle to the top.
  f-      Subtract all indices from the index of the opposite corner, producing
          the second triangle of the face.
  +       Concatenate the indices of the two triangles, resulting in a list with
          the 6 vertex indices for the face.
  _       Copy the list.
  @       Bring the offset between the two faces to the top.
  f+      Add the offset to each index in the copied list.
  W%      Revert the order, resulting in the properly oriented list of the 6 vertex
          indices for the parallel face.
}%      End of loop over 3 coordinate directions.
`       Convert to string for output. Done with triangles.

这真的很酷。。。喜欢对称性……
明亮的

这显然是最有趣的答案,但是我弄乱了我的问题定义,使其具有静态描述和“无输入”,因此我必须遵守协议并授予以下最低的字符数(这也是一个有趣的答案,但在不同的方式),答案复选标记。感谢您的参与。
不要亮

1

JavaScript(ES6)78

alert([...'1010011100101110111:120213756465240426735153410145763236'].join` `)

抱歉,没有输入我真的不理解这些挑战。


抱歉,这是我的第一个高尔夫问题。我想现在更改它为时已晚...
不要亮

下次再好。反正你有我的票。
edc65

1

红宝石,98 106

修复了Reto Koradi发现的错误。

s=sprintf'%024b',342391
6.times{|i|t='15462315'[i,3];t+=t.reverse;t[1+i%2*3]='07'[i%2];s+=t}
p s.split(//)

考虑到需要坐标,唯一有意义的角编号方案似乎是每个角都是其坐标的二进制表示的方案。这与链接的问题完全不同,链接的问题尝试了各种不同的编号方案。最后,我决定用肮脏的硬代码打印坐标:s初始化为24位数字的字符串版本,000001010011100101110111其十进制表示形式为342391。实际上,通过这种打印坐标的方法,顶点的编号是灵活的,所以我可以再做一个答案。

绕着立方体的赤道,我们找到顶点1,5,4,6,2,3,我们可以从该列表上的任何3个连续数字中为每个面定义一个三角形(从头到尾包装)。 )通过反转数字,并适当地用0或7代替中间数字,定义每个面上的另一个三角形。

这将提供所有必需的输出,但没有任何分隔字符。为此,我只需转换为一个字符数组并打印该数组,如下所示(插入换行符以防止滚动):

["0", "0", "0", "0", "0", "1", "0", "1", "0", "0", "1", "1", "1", "0", "0",
 "1", "0", "1", "1", "1", "0", "1", "1", "1", "1", "0", "4", "4", "5", "1",
 "5", "4", "6", "6", "7", "5", "4", "0", "2", "2", "6", "4", "6", "2", "3",
 "3", "7", "6", "2", "0", "1", "1", "3", "2", "3", "1", "5", "5", "7", "3"]

您确定缠绕顺序是否一致?根据我的草图,1, 5, 4是CCW,5, 4, 6是CW。
Reto Koradi

@RetoKoradi固定为8个字节。谢谢。另外,我意识到使用其他编号方案可能会做得更好。
级圣河

1

Haskell,38个字符

f=mapM(mapM print.show)"⭧勛囃勦⾽仵ᶌﻘꚱ쥎➡˻ì"

打印正确的数字,并用大量垃圾隔开:

'\''
'\\'
'1'
'1'
'1'
'1'
'1'
'\''
'\''
'\\'
'2'
'1'
'2'
'1'
'1'
...

立方体的对角线是从(1、1、1)到(2、2、2)。


1

CJam,20个字符

"⭧勛囃勦⾽仵ᶌﻘꚱ쥎➡˻ì":isS*

与我的Haskell回答相同的想法;印刷品:

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

1

Ruby,修订版1 62

29.downto(0){|c|p c>5?73888640>>c&1:[c,c^1,c|6,c|6,(c+3)%6,c]}

c-6通过将幻数乘以64来摆脱。

坐标分配如下。我分配100给数字1很奇怪,我可以通过交换轴并分配001给数字1来在rev 0中保存一个字节。之所以这样,是因为最初我在循环中向上计数,这意味着我必须将所有内容反过来放在魔术弦中。无论如何,随着我现在所做的更改,没有其他可保存的内容,因此我将原样保留坐标

Cube rotated with 0163 face at back
Top layer from above
01   000 100
74   010 110    
Bottom layer from above
36   001 101   
25   011 111

Ruby,修订版0 63

29.downto(0){|c|p c>5?1154510>>c-6&1:[c,c^1,c|6,c|6,(c+3)%6,c]}

使用坐标数据的硬编码可以灵活地选择拐角。输出中有54位数字,这意味着幼稚的解决方案将有63-54 = 9个字节可用于代码。由于我无法想到在9个字节中插入空格的方法,因此我认为这比幼稚的解决方案要短。

编号方案(从我对链接问题https://codegolf.stackexchange.com/a/48867/15599的 Ruby答案中改编而成)

4---7
|  /|
| / |
|/  |
1---0---7
|  /|  /|
| / | / |
|/  |/  |
6---3---2---7
    |  /|  /|
    | / | / |
    |/  |/  |
    6---5---4
        |  /|
        | / |
        |/  |
        6---1

输出量

0
0
0
1
0
0
0
1
1
0
0
1
1
1
0
1
1
1
0
0
1
1
1
0
[5, 4, 7, 7, 2, 5]
[4, 5, 6, 6, 1, 4]
[3, 2, 7, 7, 0, 3]
[2, 3, 6, 6, 5, 2]
[1, 0, 7, 7, 4, 1]
[0, 1, 6, 6, 3, 0]

我真的很喜欢掺入@ Runer112的方法
不要亮

@donbright我是第一个想到在前一个问题中将前6个顶点放在赤道上并将后2个放在极点上的人,这就是为什么我的C答案是最受欢迎的答案。我按顺序有6个顶点。Runer112因对赤道上的6个顶点进行了重新排序而值得赞扬。我不得不在上一个问题上修改Ruby的面部顺序,但是顶点顺序确实与Runer112相同。菲诺特在赤道上对6个顶点的替代重新排序将使我在上一个问题上具有相同的长度,但在这个问题上会更长一些
Level River St

太棒了...感谢您的详细解释...非常有趣。我应该允许输入的,这将是一个更好的挑战。
唐明亮
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.