Imprimir os vértices de um cubo e seus triângulos de cobertura


9

Coordenadas de saída dos vértices de um cubo. Em seguida, produza uma lista de doze triângulos que cobrirão o cubo, cada triângulo sendo uma lista de três índices de vértices, sempre orientados. A saída deve ser uma sequência ASCII de números decimais distintos. Este golfe não tem entrada. O vencedor é o menor número de caracteres, em que o conjunto de caracteres é Unicode.

Por exemplo, considere um cubo 1x1x1 encurralado em 0,0,0. Os oito vértices do cubo podem ser descritos pelas seguintes coordenadas xyz em uma grade 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)

Cada vértice pode receber um í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

Agora considere a face superior, vértices indexados de zero a três. Os dois triângulos de cobertura podem ser descritos por três índices cada:

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

Aqui está uma foto dessa face superior, vista de cima do cubo:

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

E aqui está uma visão de um ângulo.

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

Observe que a orientação, ou "enrolamento", desses dois triângulos é "anti-horário" quando vista de "fora" do cubo, olhando diretamente para a face em questão (imagine visitar cada vértice conforme listado, no sentido anti-horário). Agora imagine isso feito para todos os seis lados do 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]

Você pode gerar qualquer tamanho de cubo localizado em qualquer coordenada. Você pode numerar e ordenar as coordenadas do vértice da maneira que desejar. Os índices podem ser baseados em 0 ou 1. A orientação do triângulo pode ser no sentido horário ou anti-horário quando vista de fora do cubo, desde que seja consistente para todos os triângulos.

A saída pode ser formatada como você desejar, desde que cada número decimal ASCII seja separado por pelo menos um caractere ASCII não numérico. Por exemplo, o exemplo acima também pode ser exibido da seguinte maneira:

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 golfe é inspirado em vários sistemas e formatos de gráficos 3D, incluindo OpenGL, OBJ, OFF, AMF, CGAL, etc. Este golfe é semelhante ao golfe dos Hobbies da Calvin chamado Output a Face on a Nube Cube , a grande diferença é que você precisa para gerar as coordenadas xyz dos vértices e os índices do triângulo. Obrigado pela leitura.

Por inspiração do usuário, aqui está um programa de validação "auxiliar" em python2 (não-golfista) que imprimirá 'ok' ou 'não ok' para dados de saída de teste nas variáveis ​​vertstr e idxstr. Não funciona perfeitamente ... mas pode detectar alguns erros.

Editar: erro de digitação corrigido no exemplo e erros no código de validação.

    

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

classe Vector:
    def __init __ (auto, v):
        self.x, self.y, self.z = v [0], v [1], v [2]
    def __add__ (self, v):
        return Vector ([self.x + vx, self.y + vy, self.z + vz])
    def __sub __ (auto, v):
        return Vector ([self.xv.x, self.yv.y, self.zv.z])
    def __str __ (próprio):
        Retorno str (self.x) + ',' + str (self.y) + ',' + str (self.z)

def cruz (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
    return Vector ([x, y, z])

# http://mathforum.org/library/drmath/view/55343.html & http://sympy.org
def enrolamento (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 
    retornar d

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


def triplicar (str):
    nums, triplos = [], []
    para num em str.split (''): nums + = [int (num)]
    para i no intervalo (0, len (nums), 3):
        triplos + = [[nums [i], nums [i + 1], nums [i + 2]]]
    retorno tripla

verts = triplicar (vertstr)
índices = triplicar (idxstr)
nsum = Vetor ([0,0,0])
windsum = 0
xs, ys, zs = [], [], []
para v em verts:
    xs + = [v [0]]
    ys + = [v [1]]
    zs + = [v [2]]
#print xs, ys, zs, len (xs)
center = Vetor ([float (soma (xs)) / len (xs), float (soma (ys)) / len (ys), float (soma (zs)) / len (zs)])
para triângulo em índices:
    v1 = Vetor (verts [triângulo [0]])
    v2 = Vetor (verts [triângulo [1]])
    v3 = Vetor (verts [triângulo [2]])
    normas = normais (v1, v2, v3)
    imprimir v1, v2, v3, normas [0], normas [1], normas [2]
    para n em normas:
        nsum + = n
    w = enrolamento (v1, v2, v3, centro)
    imprimir 'enrolamento', w
    se w <0: windsum- = 1
    elif w> 0: windsum + = 1
if abs (windsum) == 12: imprime 'enrolamento ok'
else: print 'enrolamento não está ok'
if (nsum.x == 0 e nsum.y == 0 e nsum.z == 0): imprime 'soma normal ok'
else: imprimir 'soma normal não está ok'

11
É claro a partir do exemplo, mas apenas para torná-lo perfeitamente inequívoco, convém mencionar que os índices são baseados em 0. Isso não é um dado, pois pelo menos um dos formatos listados como exemplo (OBJ) usa índices baseados em 1.
Reto Koradi 19/10/2015

Isso também funcionará. Eu acho que uma dificuldade nesse desafio é que é moderadamente doloroso verificar a exatidão da saída. Você praticamente precisa desenhar um cubo com o vértice escolhido em um pedaço de papel e validar manualmente todos os 12 triângulos. Bem, você pode escrever um programa de validação. Na verdade, isso pode ser outra ideia de desafio ... mais difícil que esta, eu acho.
Reto Koradi 19/10/2015

Eu realmente gosto da idéia de outro golfe para um validador. Eu atualizei o exemplo para fornecer um conjunto de dados completo. obrigado novamente.
don brilhante

ok Eu adicionei um programa de validação muito rápido e sujo que pega produtos cruzados de cada par de vetores em cada triângulo, adiciona todos eles e se 0 diz 'ok'.
don brilhante

Respostas:


1

Pitão, 18 caracteres

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

Mesma ideia que minha resposta de Haskell; impressões:

[
1
1
1
1
1
,

2
1
2
1
1
...

Eu amo que você usou a mesma seqüência de caracteres Unicode em 3 idiomas diferentes
don brilhante

11
O que é essa mágica unicode?
RK.

2

CJam, 35 bytes

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

Experimente online

A saída é:

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

A orientação do triângulo é no sentido horário a partir do exterior. Eu verifiquei isso manualmente, e parece correto para mim.

Explicação:

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.

Isso é muito legal. . . amo a simetria ...
don bright

essa é claramente a resposta mais divertida, mas eu estraguei minha definição de problema para ter uma descrição estática e "nenhuma entrada", por isso tenho que manter o acordo e atribuir a menor contagem de caracteres abaixo (o que também é uma resposta divertida, mas em um maneira diferente), a marca de seleção Resposta. obrigado por participar.
don brilhante

1

JavaScript (ES6) 78

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

Desculpe, mas eu realmente não entendo esses desafios sem nenhuma entrada.


desculpe, foi a minha primeira pergunta de golfe. Eu acho que é tarde demais para mudá-lo agora ...
don bright

Melhor da próxima vez. Você tem meu voto de qualquer maneira.
Edc65

1

Ruby, 98 106

Corrigido o erro 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 as coordenadas são necessárias, o único esquema de numeração de cantos que fazia sentido parecia ser aquele em que cada canto é a representação binária de suas coordenadas. Isso é bem diferente da questão vinculada, onde vários esquemas de numeração diferentes foram tentados. No final, decidi imprimir as coordenadas com um código rígido sujo: sé inicializado para a versão em cadeia do número de 24 bits 000001010011100101110111cuja representação decimal é 342391. Na verdade, com esse método de impressão de coordenadas, a numeração dos vértices é flexível, portanto, posso faça outra resposta.

Contornando o equador do cubo, encontramos os vértices 1,5,4,6,2,3 e podemos definir um triângulo para cada face a partir de três números consecutivos nesta lista (retornando ao início no final. ) O outro triângulo em cada face é definido revertendo os dígitos e substituindo o dígito do meio por 0 ou 7, conforme apropriado.

Isso fornece toda a saída necessária, mas sem caracteres de separação. Para conseguir isso, basta converter para uma matriz de caracteres e imprimir a matriz, desta forma (quebras de linha inseridas para impedir a rolagem):

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

Tem certeza de que a ordem do enrolamento é consistente? Com base no meu esboço, 1, 5, 4é CCW, 5, 4, 6é CW.
Reto Koradi

@RetoKoradi corrigido a um custo de 8 bytes. Obrigado. Além disso, percebi que posso me sair melhor com um esquema de numeração diferente.
Level River St

1

Haskell, 38 caracteres

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

Imprime os números certos, separados por um monte de lixo:

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

A diagonal do cubo é de (1, 1, 1) a (2, 2, 2).


1

CJam, 20 caracteres

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

Mesma ideia que minha resposta de Haskell; impressões:

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, Rev. 1 62

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

Livre-se disso c-6multiplicando o número mágico por 64.

A atribuição de coordenadas está abaixo. É estranho que eu tenha atribuído 100ao número 1. Eu poderia ter salvo um byte na rev. 0 trocando os eixos e atribuído 001ao número 1. O motivo foi assim porque originalmente eu tinha contado no loop, o que significava que eu teve que colocar tudo ao contrário na corda mágica. De qualquer forma, com a alteração que fiz agora, não há economia adicional a ser feita, então deixarei as coordenadas como estão

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 codificação codificada dos dados das coordenadas para dar flexibilidade na escolha dos cantos. Existem 54 dígitos na saída, significando que a solução ingênua teria 63-54 = 9 bytes disponíveis para o código. Como não consigo pensar em uma maneira de inserir espaços em 9 bytes, acredito que isso seja mais curto que a solução ingênua.

Esquema de numeração (adaptado da minha resposta Ruby à pergunta vinculada https://codegolf.stackexchange.com/a/48867/15599 )

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

Resultado

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]

Eu realmente gosto da incorporação do método de @ Runer112
don bright

@donbright Fui o primeiro a pensar em colocar os 6 primeiros vértices no equador e os 2 últimos nos pólos da pergunta anterior, e é por isso que minha resposta C é a resposta mais popular. Eu tinha os 6 vértices em ordem seqüencial. Runer112 merece algum crédito por reordenar os 6 vértices no equador. Eu tive que modificar a ordem de face do Ruby na pergunta anterior, mas a ordem do vértice é realmente idêntica à do Runer112. A reordenação alternativa de Phinotphi dos 6 vértices no equador me daria o mesmo comprimento na pergunta anterior, mas seria mais longa neste caso
Level River St St

uau incrível ... obrigado pela explicação detalhada ... muito interessante. eu deveria ter permitido a entrada, então teria sido um desafio melhor.
don brilhante
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.