Imprime los vértices de un cubo y sus triángulos de cobertura.

9

Coordenadas de salida de los vértices de un cubo. Luego, emite una lista de doce triángulos que cubrirán el cubo, cada triángulo es una lista de tres índices de vértices, orientados consistentemente. La salida debe ser una cadena ASCII de números decimales distintos. Este golf no tiene entrada. El ganador es la menor cantidad de caracteres, donde el conjunto de caracteres es Unicode.

Por ejemplo, considere un cubo 1x1x1 arrinconado a 0,0,0. Los ocho vértices del cubo se pueden describir mediante las siguientes coordenadas xyz en una cuadrícula cartesiana 3d:

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)

A cada vértice se le puede dar un índice: 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

Ahora considere la cara superior, vértices indexados de cero a tres. Los dos triángulos de cobertura se pueden describir mediante tres índices cada uno:

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

Aquí hay una foto de esta cara superior, vista desde arriba del cubo:

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

Y aquí hay una vista desde un ángulo.

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

Tenga en cuenta que la orientación, o 'devanado', de ambos triángulos es 'en sentido contrario a las agujas del reloj' cuando se ve desde 'fuera' del cubo mirando directamente a la cara en cuestión (imagine visitar cada vértice como se indica, va en sentido antihorario). Ahora imagine esto hecho para los seis lados del cubo.

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]

Puede generar cualquier tamaño de cubo ubicado en cualquier coordenada. Puede numerar y ordenar las coordenadas de vértice como lo desee. Los índices pueden estar basados ​​en 0 o en 1. La orientación del triángulo puede ser en sentido horario o antihorario cuando se ve desde fuera del cubo, siempre que sea consistente para todos los triángulos.

La salida se puede formatear como desee, siempre que cada número decimal ASCII esté separado por al menos un carácter ASCII no numérico. Por ejemplo, el ejemplo anterior también se puede generar de la siguiente manera:

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

Este golf está inspirado en varios sistemas y formatos de gráficos en 3D, incluidos OpenGL, OBJ, OFF, AMF, CGAL, etc. Este golf es similar al golf de Calvin's Hobbies llamado Output a Face on a Numbered Cube , la gran diferencia es que usted necesita para generar las coordenadas xyz de los vértices y generar índices de triángulos. Gracias por leer.

Por inspiración del usuario, aquí hay un programa de validación "auxiliar" en python2 (no apto para golf) que imprimirá 'ok' o 'not ok' para datos de salida de prueba en las variables vertstr e idxstr. No funciona perfectamente ... pero puede detectar algunos errores.

Editar: error tipográfico fijo en el ejemplo y errores en el código de validación.

    

#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 1 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'

Vector de clase:
    def __init __ (self, v):
        self.x, self.y, self.z = v [0], v [1], v [2]
    def __add __ (self, v):
        Vector de retorno ([self.x + vx, self.y + vy, self.z + vz])
    def __sub __ (self, v):
        Vector de retorno ([self.xv.x, self.yv.y, self.zv.z])
    def __str __ (self):
        return str (self.x) + ',' + str (self.y) + ',' + str (self.z)

cruz cruzada (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
    Vector de retorno ([x, y, z])

# http://mathforum.org/library/drmath/view/55343.html y http://sympy.org
devanado 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 
    volver d

def normales (v1, v2, v3):
    va = v2-v1
    vb = v3-v2
    vc = v1-v3
    n1 = cruz (va, vb)
    n2 = cruz (vb, vc)
    n3 = cruz (vc, va)
    volver [n1, n2, n3]


def triplify (str):
    nums, triples = [], []
    para num en str.split (''): nums + = [int (num)]
    para i en rango (0, len (nums), 3):
        triples + = [[nums [i], nums [i + 1], nums [i + 2]]]
    triples de regreso

verts = triplify (vertstr)
índices = triplificar (idxstr)
nsum = Vector ([0,0,0])
Windsum = 0
xs, ys, zs = [], [], []
para v en verts:
    xs + = [v [0]]
    ys + = [v [1]]
    zs + = [v [2]]
#print xs, ys, zs, len (xs)
centro = Vector ([float (sum (xs)) / len (xs), float (sum (ys)) / len (ys), float (sum (zs)) / len (zs)])
para triángulo en índices:
    v1 = Vector (verts [triángulo [0]])
    v2 = Vector (verts [triángulo [1]])
    v3 = Vector (verts [triángulo [2]])
    normas = normales (v1, v2, v3)
    imprimir v1, v2, v3, normas [0], normas [1], normas [2]
    para n en las normas:
        nsum + = n
    w = devanado (v1, v2, v3, centro)
    imprimir 'bobinado', w
    si w <0: windsum- = 1
    elif w> 0: viento + = 1
if abs (windsum) == 12: imprime 'bobinado ok'
más: imprima 'bobinado no está bien'
if (nsum.x == 0 y nsum.y == 0 y nsum.z == 0): imprime 'suma normal ok'
de lo contrario: imprima 'suma normal no está bien'
don brillante
fuente
1
Está claro en el ejemplo, pero solo para hacerlo perfectamente inequívoco, es posible que desee mencionar que los índices están basados ​​en 0. Esto no es un hecho dado, ya que al menos uno de los formatos que enumera como ejemplo (OBJ) usa índices basados ​​en 1.
Reto Koradi
Eso también funcionará. Creo que una dificultad con este desafío es que es moderadamente doloroso verificar la corrección de la salida. Tiene que dibujar un cubo con el orden de vértice elegido en una hoja de papel y validar manualmente los 12 triángulos. Bueno, podrías escribir un programa de validación. Esa podría ser otra idea de desafío ... más difícil que esta, creo.
Reto Koradi
Me gusta mucho la idea de otro golf para un validador. Actualicé el ejemplo para dar un conjunto de datos completo. gracias de nuevo.
Don brillante
ok Agregué un programa de validación muy rápido y sucio que toma productos cruzados de cada par de vectores en cada triángulo, los agrega a todos y si 0 dice 'ok'.
Don brillante

Respuestas:

1

Pyth, 18 caracteres

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

La misma idea que mi respuesta de Haskell; huellas dactilares:

[
1
1
1
1
1
,

2
1
2
1
1
...
Lynn
fuente
me encanta que hayas usado la misma cadena Unicode en 3 idiomas diferentes
don bright
1
¿Qué es esta magia unicode?
RK.
2

CJam, 35 bytes

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

Pruébalo en línea

El resultado es:

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

La orientación del triángulo es en sentido horario desde el exterior. Lo comprobé manualmente y me parece correcto.

Explicación:

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.
Reto Koradi
fuente
esto es realmente genial. . . Amo la simetría ...
Don Bright
esta es claramente la respuesta más divertida, pero confundí mi definición de problema para tener una descripción estática y "no ingresar", así que tengo que mantener el acuerdo y otorgar el recuento de caracteres más bajo, a continuación (que también es una respuesta divertida pero en un manera diferente), la marca de verificación Respuesta. Gracias por participar.
Don brillante
1

JavaScript (ES6) 78

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

Lo siento, pero realmente no entiendo estos desafíos sin aportes.

edc65
fuente
lo siento, fue mi primera pregunta de golf. supongo que es demasiado tarde para cambiar ahora ...
don brillante
Mejor la próxima vez. Tienes mi voto de todos modos.
edc65
1

Ruby, 98 106

Se corrigió el error detectado por 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(//)

Dado que se requieren coordenadas, el único esquema de numeración de esquinas que tenía sentido parecía ser aquel en el que cada esquina es la representación binaria de sus coordenadas. Eso es bastante diferente de la pregunta vinculada, donde se probaron varios esquemas de numeración diferentes. Al final decidí imprimir las coordenadas con un código rígido sucio: sse inicializa a la versión de cadena del número de 24 bits 000001010011100101110111cuya representación decimal es 342391. En realidad, con este método de impresión de coordenadas, la numeración de los vértices es flexible, por lo que puedo Haz otra respuesta.

Al dar la vuelta al ecuador del cubo, encontramos los vértices 1,5,4,6,2,3 y podemos definir un triángulo para cada cara a partir de 3 números consecutivos en esta lista (volviendo al principio al final. ) El otro triángulo en cada cara se define invirtiendo los dígitos y sustituyendo el dígito del medio con 0 o 7 según corresponda.

Esto proporciona toda la salida requerida, pero sin caracteres de separación. Para lograr eso, simplemente me convierto en una matriz de caracteres e imprimo la matriz, de esta manera (saltos de línea insertados para evitar el desplazamiento):

["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"]
Level River St
fuente
¿Está seguro de que el orden de bobinado es consistente? Según mi boceto, 1, 5, 4es CCW, 5, 4, 6es CW.
Reto Koradi
@RetoKoradi corregido a un costo de 8 bytes. Gracias. Además, me di cuenta de que podría hacerlo mejor con un esquema de numeración diferente.
Level River St
1

Haskell, 38 personajes

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

Imprime los números correctos, separados por una gran cantidad de basura:

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

La diagonal del cubo es de (1, 1, 1) a (2, 2, 2).

Lynn
fuente
1

CJam, 20 caracteres

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

La misma idea que mi respuesta de Haskell; huellas dactilares:

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
Lynn
fuente
1

Ruby, Rev 1 62

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

Se deshizo del c-6multiplicando el número mágico por 64.

La asignación de coordenadas está abajo. Es extraño que asigné 100al número 1. Podría haber guardado un byte en rev 0 intercambiando los ejes y asignando 001al número 1. La razón por la que fue así fue porque originalmente tenía un conteo en el bucle, lo que habría significado que yo tuvo que poner todo al revés en la cuerda mágica. De todos modos, con el cambio que he hecho ahora, no hay ahorro adicional que hacer, así que dejaré las coordenadas como están

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, Rev 0 63

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

Usando la codificación de los datos de coordenadas para dar flexibilidad en la elección de las esquinas. Hay 54 dígitos en la salida, lo que significa que la solución ingenua tendría 63-54 = 9 bytes disponibles para el código. Como no puedo pensar en una forma de insertar espacios en 9 bytes, creo que esto es más corto que la solución ingenua.

Esquema de numeración (adaptado de mi respuesta de Ruby a la pregunta vinculada https://codegolf.stackexchange.com/a/48867/15599 )

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

Salida

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]
Level River St
fuente
Realmente me gusta la incorporación del método de @ Runer112
don bright
@donbright Fui el primero en pensar en poner los primeros 6 vértices en el ecuador y los últimos 2 en los polos en esa pregunta anterior, por lo que mi respuesta C es la respuesta más popular. Tenía los 6 vértices en orden secuencial. Runer112 merece algo de crédito por su reordenamiento de los 6 vértices en el ecuador. Tuve que modificar el orden de la cara de Ruby en la pregunta anterior, pero el orden de los vértices es idéntico al de Runer112. La reordenación alternativa de Phinotphi de los 6 vértices en el ecuador me hubiera dado la misma longitud en la pregunta anterior, pero sería más larga en esta
Level River St
wow increíble ... gracias por la explicación detallada ... muy interesante. Debería haber permitido la entrada, entonces habría sido un mejor desafío.
Don brillante