Imprimer les sommets d'un cube et ses triangles de couverture

9

Coordonnées de sortie des sommets d'un cube. Ensuite, affichez une liste de douze triangles qui couvriront le cube, chaque triangle étant une liste de trois index de sommet, orientés de manière cohérente. La sortie doit être une chaîne ASCII de nombres décimaux distincts. Ce golf n'a pas d'entrée. Le gagnant est le moins de caractères, où le jeu de caractères est Unicode.

Par exemple, considérons un cube 1x1x1 coincé à 0,0,0. Les huit sommets du cube peuvent être décrits par les coordonnées xyz suivantes sur une grille cartésienne 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)

Chaque sommet peut recevoir un index: 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

Considérons maintenant la face supérieure, les sommets indexés de zéro à trois. Les deux triangles de recouvrement peuvent être décrits par trois indices chacun:

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

Voici une photo de cette face supérieure, vue du dessus du cube:

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

Et voici une vue sous un angle.

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

Notez que l'orientation, ou `` enroulement '', de ces deux triangles est `` dans le sens inverse des aiguilles d'une montre '' lorsqu'elle est vue `` à l'extérieur '' du cube en regardant directement la face en question (imaginez visiter chaque sommet comme indiqué, il va dans le sens antihoraire). Imaginez maintenant que cela soit fait pour les six côtés du cube.

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]

Vous pouvez sortir n'importe quelle taille de cube situé à n'importe quelle coordonnée. Vous pouvez numéroter et ordonner les coordonnées des sommets comme vous le souhaitez. Les indices peuvent être basés sur 0 ou basés sur 1. L'orientation du triangle peut être dans le sens horaire ou antihoraire lorsqu'il est vu de l'extérieur du cube tant qu'il est cohérent pour tous les triangles.

La sortie peut être formatée comme vous le souhaitez, tant que chaque nombre décimal ASCII est séparé par au moins un caractère ASCII non numérique. Par exemple, l'exemple ci-dessus peut également être généré comme suit:

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

Ce golf est inspiré par divers systèmes et formats graphiques 3D, notamment OpenGL, OBJ, OFF, AMF, CGAL, etc. Ce golf est similaire au golf de Calvin's Hobbies nommé Output a Face on a Numbered Cube , la grande différence étant que vous avez besoin pour sortir vous-même les coordonnées xyz des sommets et afficher les indices des triangles. Merci d'avoir lu.

Par inspiration utilisateur, voici un programme de validation "assistant" en python2 (non-golfy) qui affichera 'ok' ou 'not ok' pour les données de sortie de test dans les variables vertstr et idxstr. Cela ne fonctionne pas parfaitement ... mais il peut attraper des erreurs.

Edit: correction d'une faute de frappe dans l'exemple et de bugs dans le code de validation.

    

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

vecteur de classe:
    def __init __ (auto, v):
        self.x, self.y, self.z = v [0], v [1], v [2]
    def __add __ (auto, v):
        vecteur de retour ([self.x + vx, self.y + vy, self.z + vz])
    def __sub __ (auto, v):
        vecteur de retour ([self.xv.x, self.yv.y, self.zv.z])
    def __str __ (auto):
        retourne 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
    retourner le vecteur ([x, y, z])

# http://mathforum.org/library/drmath/view/55343.html & http://sympy.org
enroulement 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 
    retour d

normales normales (v1, v2, v3):
    va = v2-v1
    vb = v3-v2
    vc = v1-v3
    n1 = croix (va, vb)
    n2 = croix (vb, vc)
    n3 = croix (vc, va)
    retourner [n1, n2, n3]


def triplify (str):
    nums, triples = [], []
    pour num dans str.split (''): nums + = [int (num)]
    pour i dans la plage (0, len (nums), 3):
        triples + = [[nums [i], nums [i + 1], nums [i + 2]]]
    retourner des triplets

verts = triplify (vertstr)
indices = triplifier (idxstr)
nsum = vecteur ([0,0,0])
windsum = 0
xs, ys, zs = [], [], []
pour v in verts:
    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)]]
pour le triangle dans les indices:
    v1 = vecteur (verts [triangle [0]])
    v2 = vecteur (verts [triangle [1]])
    v3 = vecteur (verts [triangle [2]])
    normes = normales (v1, v2, v3)
    imprimer v1, v2, v3, normes [0], normes [1], normes [2]
    pour n dans les normes:
        nsum + = n
    w = enroulement (v1, v2, v3, centre)
    imprimer «enroulement», w
    si w <0: somme de vent- = 1
    elif w> 0: somme de vent + = 1
si abs (windsum) == 12: affichez 'winding ok'
sinon: imprimer «enroulement pas ok»
if (nsum.x == 0 et nsum.y == 0 et nsum.z == 0): affichez 'somme normale ok'
sinon: affichez 'somme normale pas ok'
Don Bright
la source
1
C'est clair à partir de l'exemple, mais juste pour le rendre parfaitement sans ambiguïté, vous voudrez peut-être mentionner que les indices sont basés sur 0. Ce n'est pas une donnée, car au moins l'un des formats que vous citez comme exemple (OBJ) utilise des indices basés sur 1.
Reto Koradi
Cela fonctionnera également. Je pense qu'une difficulté avec ce défi est qu'il est modérément pénible de vérifier l'exactitude de la sortie. Vous devez à peu près esquisser un cube avec l'ordre des sommets choisi sur une feuille de papier et valider manuellement les 12 triangles. Eh bien, vous pourriez écrire un programme de validation. Cela pourrait en fait être une autre idée de défi ... plus difficile que celle-ci, je pense.
Reto Koradi
j'aime vraiment cette idée d'un autre golf pour un validateur. j'ai mis à jour l'exemple pour donner un ensemble de données complet. Merci encore.
don bright
ok j'ai ajouté un programme de validation très rapide et sale qui prend les produits croisés de chaque paire de vecteurs dans chaque triangle, les ajoute tous, et si 0 dit 'ok'.
Don

Réponses:

1

Pyth, 18 caractères

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

Même idée que ma réponse Haskell; impressions:

[
1
1
1
1
1
,

2
1
2
1
1
...
Lynn
la source
j'adore le fait que vous ayez utilisé la même chaîne unicode dans 3 langues différentes
don bright
1
Quelle est cette magie unicode?
RK.
2

CJam, 35 octets

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

Essayez-le en ligne

La sortie est:

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

L'orientation du triangle est dans le sens horaire de l'extérieur. J'ai vérifié cela manuellement et cela me semble correct.

Explication:

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
la source
c'est vraiment cool. . . j'adore la symétrie ...
don bright
c'est clairement la réponse la plus amusante, mais j'ai foiré ma définition de problème pour avoir une description statique et "pas d'entrée", donc je dois garder l'accord et attribuer le nombre de caractères le plus bas, ci-dessous (qui est aussi une réponse amusante mais dans un manière différente), la coche Réponse. merci d'avoir participé.
don bright
1

JavaScript (ES6) 78

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

Désolé mais je ne comprends vraiment pas ces défis sans aucune contribution.

edc65
la source
désolé, c'était ma première question sur le golf. Je suppose qu'il est trop tard pour le changer maintenant ...
Don
Mieux la prochaine fois. Vous avez quand même mon vote.
edc65
1

Rubis, 98 106

Correction d'une erreur repérée par 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(//)

Étant donné que les coordonnées sont nécessaires, le seul schéma de numérotation des coins qui avait du sens semblait être celui où chaque coin est la représentation binaire de ses coordonnées. C'est assez différent de la question liée, où différents schémas de numérotation différents ont été essayés. En fin de compte, j'ai décidé d'imprimer les coordonnées avec un code dur sale: sest initialisé à la version chaîne de nombre 24 bits 000001010011100101110111dont la représentation décimale est 342391. En fait avec cette méthode d'impression des coordonnées, la numérotation des sommets est flexible, donc je peux faites une autre réponse.

En faisant le tour de l'équateur du cube, nous trouvons les sommets 1,5,4,6,2,3 et nous pouvons définir un triangle pour chaque face à partir de 3 nombres consécutifs sur cette liste (en revenant au début à la fin. ) L'autre triangle de chaque face est défini en inversant les chiffres et en remplaçant le chiffre du milieu par 0 ou 7 selon le cas.

Cela donne toute la sortie requise, mais sans aucun caractère de séparation. Pour y parvenir, je convertis simplement en un tableau de caractères et j'imprime le tableau, comme ceci (sauts de ligne insérés pour empêcher le défilement):

["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
la source
Êtes-vous sûr que l'ordre d'enroulement est cohérent? Basé sur mon croquis, 1, 5, 4est CCW, 5, 4, 6est CW.
Reto Koradi
@RetoKoradi fixé à un coût de 8 octets. Merci. De plus, j'ai réalisé que je pourrais faire mieux avec un schéma de numérotation différent.
Level River St
1

Haskell, 38 caractères

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

Imprime les bons chiffres, séparés par un tas d'ordure:

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

La diagonale du cube est de (1, 1, 1) à (2, 2, 2).

Lynn
la source
1

CJam, 20 caractères

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

Même idée que ma réponse Haskell; impressions:

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
la source
1

Ruby, Rév 1 62

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

Je me suis débarrassé du c-6en multipliant le nombre magique par 64.

L'affectation des coordonnées est ci-dessous. C'est étrange que j'aie attribué 100au numéro 1. J'aurais pu enregistrer un octet dans le rev 0 en échangeant les axes et en les affectant 001au numéro 1. La raison en était que c'était parce qu'à l'origine j'avais compté dans la boucle, ce qui aurait signifié que je a dû tout mettre en sens inverse dans la chaîne magique. Quoi qu'il en soit, avec le changement que j'ai fait maintenant, il n'y a pas d'économie supplémentaire à faire, donc je vais laisser les coordonnées telles qu'elles sont

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, Rév 0 63

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

Utilisation du codage en dur des données de coordonnées pour donner de la flexibilité dans le choix des coins. Il y a 54 chiffres dans la sortie, ce qui signifie que la solution naïve aurait 63-54 = 9 octets disponibles pour le code. Comme je ne peux pas penser à un moyen d'insérer des espaces sur 9 octets, je pense que c'est plus court que la solution naïve.

Schéma de numérotation (adapté de ma réponse Ruby à la question liée https://codegolf.stackexchange.com/a/48867/15599 )

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

Production

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
la source
J'aime vraiment l'incorporation de la méthode de @ Runer112
don bright
@donbright J'ai été le premier à penser à mettre les 6 premiers sommets sur l'équateur et les 2 derniers sur les pôles dans cette question précédente, c'est pourquoi ma réponse C est la réponse la plus populaire. J'avais les 6 sommets dans un ordre séquentiel. Runer112 mérite un certain crédit pour sa réorganisation des 6 sommets sur l'équateur. J'ai dû modifier l'ordre des faces pour Ruby sur la question précédente, mais l'ordre des sommets est en effet identique à celui de Runer112. La réorganisation alternative de Phinotphi des 6 sommets sur l'équateur m'aurait donné une longueur égale sur la question précédente, mais serait plus longue sur celle-ci
Level River St
wow génial ... merci pour l'explication détaillée ... très intéressant. j'aurais dû autoriser la saisie, cela aurait été un meilleur défi.
don bright