Drucken Sie die Eckpunkte eines Würfels und seine Deckdreiecke

9

Ausgabekoordinaten der Eckpunkte eines Würfels. Geben Sie dann eine Liste mit zwölf Dreiecken aus, die den Würfel abdecken. Jedes Dreieck ist eine Liste mit drei Scheitelpunktindizes, die konsistent ausgerichtet sind. Die Ausgabe muss eine ASCII-Zeichenfolge mit unterschiedlichen Dezimalzahlen sein. Dieser Golf hat keine Eingabe. Gewinner sind die wenigsten Zeichen, wobei der Zeichensatz Unicode ist.

Betrachten Sie als Beispiel einen 1x1x1-Würfel mit einer Ecke von 0,0,0. Die acht Eckpunkte des Würfels können durch die folgenden xyz-Koordinaten in einem kartesischen 3D-Gitter beschrieben werden:

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)

Jeder Scheitelpunkt kann mit einem Index versehen werden: 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

Betrachten Sie nun die Oberseite, die Scheitelpunkte sind null bis drei. Die zwei Deckdreiecke können durch jeweils drei Indizes beschrieben werden:

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

Hier ist ein Bild von dieser Oberseite, von oben gesehen über dem Würfel:

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

Und hier ist ein Blick aus einem Winkel.

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

Beachten Sie, dass die Ausrichtung oder "Wicklung" dieser beiden Dreiecke "gegen den Uhrzeigersinn" ist, wenn Sie von "außerhalb" des Würfels direkt auf das betreffende Gesicht schauen (stellen Sie sich vor, Sie besuchen jeden Scheitelpunkt wie aufgelistet, er geht gegen den Uhrzeigersinn). Stellen Sie sich nun vor, dies geschieht für alle sechs Seiten des Würfels.

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]

Sie können eine beliebige Würfelgröße an beliebigen Koordinaten ausgeben. Sie können die Scheitelpunktkoordinaten beliebig nummerieren und bestellen. Indizes können auf 0 oder 1 basieren. Die Ausrichtung des Dreiecks kann von außerhalb des Würfels betrachtet entweder im oder gegen den Uhrzeigersinn erfolgen, sofern dies für alle Dreiecke konsistent ist.

Die Ausgabe kann beliebig formatiert werden, solange jede ASCII-Dezimalzahl durch mindestens ein nicht numerisches ASCII-Zeichen getrennt ist. Zum Beispiel könnte das obige Beispiel auch wie folgt ausgegeben werden:

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

Dieser Golf ist von verschiedenen 3D-Grafiksystemen und -formaten inspiriert, darunter OpenGL, OBJ, OFF, AMF, CGAL usw. Dieser Golf ähnelt dem Golf von Calvins Hobbys " Output a Face on a Numbered Cube" , wobei der große Unterschied darin besteht, dass Sie ihn benötigen um die xyz-Koordinaten der Eckpunkte selbst auszugeben und Dreiecksindizes auszugeben. Danke fürs Lesen.

Pro Benutzerinspiration gibt es hier ein "Helfer" -Validierungsprogramm in Python2 (nicht Golf), das für Testausgabedaten in den Variablen vertstr und idxstr "ok" oder "nicht ok" druckt. Es funktioniert nicht perfekt ... aber es kann einige Fehler auffangen.

Bearbeiten: Tippfehler im Beispiel behoben und Fehler im Validierungscode.

    

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

Klasse Vektor:
    def __init __ (self, v):
        self.x, self.y, self.z = v [0], v [1], v [2]
    def __add __ (self, v):
        Rückgabevektor ([self.x + vx, self.y + vy, self.z + vz])
    def __sub __ (self, v):
        return Vector ([self.xv.x, self.yv.y, self.zv.z])
    def __str __ (Selbst):
        return 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.
    Rückgabevektor ([x, y, z])

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

def Normalen (v1, v2, v3):
    va = v2-v1
    vb = v3-v2
    vc = v1-v3
    n1 = Kreuz (va, vb)
    n2 = Kreuz (vb, vc)
    n3 = Kreuz (vc, va)
    return [n1, n2, n3]


def verdreifachen (str):
    nums, triples = [], []
    für num in str.split (''): nums + = [int (num)]
    für i im Bereich (0, len (nums), 3):
        Tripel + = [[nums [i], nums [i + 1], nums [i + 2]]]
    dreifache zurückgeben

verts = verdreifachen (vertstr)
Indizes = verdreifachen (idxstr)
nsum = Vektor ([0,0,0])
Windsum = 0
xs, ys, zs = [], [], []
für v in verts:
    xs + = [v [0]]
    ys + = [v [1]]
    zs + = [v [2]]
#print xs, ys, zs, len (xs)
center = Vektor ([float (Summe (xs)) / len (xs), float (Summe (ys)) / len (ys), float (Summe (zs)) / len (zs)])
für Dreieck in Indizes:
    v1 = Vektor (verts [Dreieck [0]])
    v2 = Vektor (verts [Dreieck [1]])
    v3 = Vektor (verts [Dreieck [2]])
    Normen = Normalen (v1, v2, v3)
    print v1, v2, v3, normen [0], normen [1], normen [2]
    für n in Normen:
        nsum + = n
    w = Wicklung (v1, v2, v3, Mitte)
    Druck 'Wicklung', w
    wenn w <0: Windsum- = 1
    elif w> 0: Windsum + = 1
if abs (windsum) == 12: drucke 'Wicklung ok'
sonst: drucke 'Wicklung nicht ok'
if (nsum.x == 0 und nsum.y == 0 und nsum.z == 0): 'normale Summe ok' drucken
sonst: drucke 'normale Summe nicht ok'
nicht hell
quelle
1
Aus dem Beispiel geht klar hervor, aber um es vollkommen eindeutig zu machen, möchten Sie vielleicht erwähnen, dass die Indizes auf 0 basieren. Dies ist nicht selbstverständlich, da mindestens eines der als Beispiel aufgeführten Formate (OBJ) 1-basierte Indizes verwendet.
Reto Koradi
Das wird auch funktionieren. Ich denke, eine Schwierigkeit bei dieser Herausforderung besteht darin, dass es mäßig schmerzhaft ist, die Richtigkeit der Ausgabe zu überprüfen. Sie müssen so ziemlich einen Würfel mit der ausgewählten Scheitelpunktreihenfolge auf einem Blatt Papier skizzieren und alle 12 Dreiecke manuell validieren. Nun, Sie könnten ein Validierungsprogramm schreiben. Das könnte tatsächlich eine weitere Herausforderung sein ... schwieriger als diese, denke ich.
Reto Koradi
Ich mag die Idee eines anderen Golfs für einen Validator wirklich. Ich habe das Beispiel aktualisiert, um einen vollständigen Datensatz zu erhalten. Danke noch einmal.
Don Bright
ok Ich habe ein sehr schnelles und schmutziges Validierungsprogramm hinzugefügt, das Kreuzprodukte jedes Vektorpaars in jedem Dreieck nimmt, sie alle hinzufügt und wenn 0 'ok' sagt.
Don Bright

Antworten:

1

Pyth, 18 Zeichen

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

Gleiche Idee wie meine Antwort von Haskell; Drucke:

[
1
1
1
1
1
,

2
1
2
1
1
...
Lynn
quelle
Ich liebe es, dass Sie die gleiche Unicode-Zeichenfolge in 3 verschiedenen Sprachen verwendet haben
Don Bright
1
Was ist diese Unicode-Magie?
RK.
2

CJam, 35 Bytes

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

Probieren Sie es online aus

Die Ausgabe ist:

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

Die Dreiecksausrichtung erfolgt von außen im Uhrzeigersinn. Ich habe dies manuell überprüft und es sieht für mich korrekt aus.

Erläuterung:

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
quelle
Das ist wirklich cool. . . liebe die Symmetrie ...
Don Bright
Dies ist eindeutig die unterhaltsamste Antwort, aber ich habe meine Problemdefinition durcheinander gebracht, um eine statische Beschreibung und "keine Eingabe" zu erhalten. Daher muss ich die Vereinbarung einhalten und die niedrigste Anzahl von Zeichen unten vergeben (was auch eine unterhaltsame Antwort ist, aber in a anders), das Häkchen Antwort. danke für die teilnahme.
Don Bright
1

JavaScript (ES6) 78

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

Entschuldigung, aber ich verstehe diese Herausforderungen ohne Eingabe wirklich nicht.

edc65
quelle
Entschuldigung, es war meine erste Golffrage. Ich denke, es ist zu spät, um es jetzt zu ändern ...
Don Bright
Besser beim nächsten Mal. Du hast sowieso meine Stimme.
edc65
1

Ruby, 98 106

Fehler von Reto Koradi behoben.

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(//)

Angesichts der Tatsache, dass Koordinaten erforderlich sind, schien das einzige sinnvolle Eckennummerierungsschema das zu sein, bei dem jede Ecke die binäre Darstellung ihrer Koordinaten ist. Das ist ganz anders als bei der verknüpften Frage, bei der verschiedene Nummerierungsschemata ausprobiert wurden. Am Ende habe ich beschlossen, die Koordinaten mit einem schmutzigen Hardcode zu drucken: swird auf die String-Version der 24-Bit-Zahl initialisiert, 000001010011100101110111deren Dezimaldarstellung 342391 ist. Tatsächlich ist bei dieser Methode zum Drucken von Koordinaten die Nummerierung der Eckpunkte flexibel, also kann ich mach eine andere Antwort.

Wenn wir den Äquator des Würfels umrunden, finden wir die Eckpunkte 1,5,4,6,2,3 und wir können ein Dreieck für jede Fläche aus 3 aufeinanderfolgenden Zahlen in dieser Liste definieren (am Ende zurück zum Anfang. ) Das andere Dreieck auf jeder Seite wird definiert, indem die Ziffern umgekehrt werden und die mittlere Ziffer durch 0 oder 7 ersetzt wird.

Dies gibt alle erforderlichen Ausgaben, jedoch ohne Trennzeichen. Um dies zu erreichen, konvertiere ich einfach in ein Array von Zeichen und drucke das Array wie folgt aus (Zeilenumbrüche eingefügt, um ein Scrollen zu verhindern):

["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.
quelle
Sind Sie sicher, dass die Wicklungsreihenfolge konsistent ist? Basierend auf meiner Skizze 1, 5, 4ist CCW, 5, 4, 6ist CW.
Reto Koradi
@RetoKoradi zu einem Preis von 8 Bytes behoben. Vielen Dank. Außerdem habe ich festgestellt, dass ich mit einem anderen Nummerierungsschema möglicherweise besser abschneiden kann.
Level River St
1

Haskell, 38 Zeichen

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

Druckt die richtigen Zahlen, getrennt durch eine ganze Menge Müll:

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

Die Diagonale des Würfels reicht von (1, 1, 1) bis (2, 2, 2).

Lynn
quelle
1

CJam, 20 Zeichen

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

Gleiche Idee wie meine Antwort von Haskell; Drucke:

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

Wurde das c-6durch Multiplizieren der magischen Zahl mit 64 los .

Die Zuordnung der Koordinaten ist unten. Es ist seltsam, dass ich 100Nummer 1 zugewiesen habe. Ich hätte ein Byte in Rev. 0 speichern können, indem ich die Achsen ausgetauscht 001und Nummer 1 zugewiesen hätte . Der Grund dafür war, dass ich ursprünglich in der Schleife gezählt hatte, was bedeutet hätte, dass ich musste alles umgekehrt in die magische Schnur setzen. Wie auch immer, mit der Änderung, die ich jetzt vorgenommen habe, müssen keine zusätzlichen Einsparungen vorgenommen werden, also lasse ich die Koordinaten so, wie sie sind

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

Verwenden Sie die Hardcodierung der Koordinatendaten, um die Auswahl der Ecken flexibel zu gestalten. Die Ausgabe enthält 54 Stellen, was bedeutet, dass für die naive Lösung 63-54 = 9 Byte für Code verfügbar sind. Da ich mir keine Möglichkeit vorstellen kann, Leerzeichen in 9 Bytes einzufügen, glaube ich, dass dies kürzer ist als die naive Lösung.

Nummerierungsschema (angepasst aus meiner Ruby-Antwort auf die verknüpfte Frage https://codegolf.stackexchange.com/a/48867/15599 )

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

Ausgabe

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.
quelle
Ich mag die Integration der Methode von @ Runer112 sehr
Don Bright
@donbright Ich war der erste, der daran dachte, die ersten 6 Eckpunkte auf den Äquator und die letzten 2 auf die Pole in dieser vorherigen Frage zu setzen, weshalb meine C-Antwort die beliebteste Antwort ist. Ich hatte die 6 Eckpunkte in sequentieller Reihenfolge. Runer112 verdient etwas Anerkennung für seine Neuordnung der 6 Eckpunkte am Äquator. Ich musste die Gesichtsreihenfolge für Ruby in der vorherigen Frage ändern, aber die Scheitelpunktreihenfolge ist tatsächlich identisch mit der von Runer112. Phinotphis alternative Neuordnung der 6 Eckpunkte am Äquator hätte mir bei der vorherigen Frage die gleiche Länge gegeben, wäre aber bei dieser Frage länger gewesen
Level River St
wow genial ... danke für die ausführliche Erklärung ... sehr interessant. Ich hätte Input zulassen sollen, dann wäre es eine bessere Herausforderung gewesen.
Don Bright