Wydrukuj wierzchołki sześcianu i otaczające go trójkąty

9

Współrzędne wyjściowe wierzchołków sześcianu. Następnie wypisz listę dwunastu trójkątów, które pokryją sześcian, przy czym każdy trójkąt jest listą trzech indeksów wierzchołków, konsekwentnie zorientowanych. Dane wyjściowe muszą być łańcuchem ASCII o różnych liczbach dziesiętnych. Ten golf nie ma wkładu. Zwycięzca to najmniej znaków, w których zestaw znaków to Unicode.

Na przykład rozważmy kostkę 1x1x1 osaczoną na 0,0,0. Osiem wierzchołków sześcianu można opisać następującymi współrzędnymi xyz na siatce kartezjańskiej 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)

Każdy wierzchołek może mieć indeks: 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

Teraz rozważ górną powierzchnię, wierzchołki indeksowane od zera do trzech. Dwa pokrywające się trójkąty można opisać za pomocą trzech wskaźników:

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

Oto zdjęcie tej górnej twarzy, widzianej z góry sześcianu:

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

A oto widok z kąta.

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

Zwróć uwagę, że orientacja lub „nawijanie” obu tych trójkątów jest „przeciwnie do ruchu wskazówek zegara”, gdy patrzy się na „z zewnątrz” sześcianu bezpośrednio patrząc na daną twarz (wyobraź sobie, że odwiedzasz każdy wierzchołek zgodnie z ruchem wskazówek zegara). Teraz wyobraź sobie, że zrobiono to dla wszystkich sześciu boków sześcianu.

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]

Możesz wyprowadzać dowolny rozmiar sześcianu znajdującego się przy dowolnej współrzędnej. Możesz numerować i porządkować współrzędne wierzchołków w dowolny sposób. Indeksy mogą być oparte na 0 lub na 1. Orientacja trójkąta może być zgodna z ruchem wskazówek zegara lub przeciwnie do ruchu wskazówek zegara, patrząc z zewnątrz sześcianu, o ile jest spójna dla wszystkich trójkątów.

Dane wyjściowe można sformatować w dowolny sposób, o ile każda liczba dziesiętna ASCII jest oddzielona co najmniej jednym nieliczbowym znakiem ASCII. Na przykład powyższy przykład można również przedstawić w następujący sposób:

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

Ten golf jest inspirowany różnymi systemami i formatami grafiki 3D, w tym OpenGL, OBJ, OFF, AMF, CGAL itp. Ten golf jest podobny do golfa autorstwa Hobby Calvina o nazwie Output a Face on the Numbered Cube , z tą dużą różnicą, że potrzebujesz aby samodzielnie wyprowadzić współrzędne xyz wierzchołków i wyprowadzić indeksy trójkątów. Dziękuje za przeczytanie.

Inspiracją dla użytkownika jest tutaj program sprawdzający „pomocnika” w python2 (inny niż golfy), który wypisze „ok” lub „nie ok” dla danych wyjściowych testu w zmiennych vertstr i idxstr. Nie działa idealnie ... ale może wykryć pewne błędy.

Edycja: poprawiono literówkę w przykładzie i błędy w kodzie sprawdzania poprawności.

    

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

klasa wektor:
    def __init __ (self, 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 __ (self, v):
        return Vector ([self.xv.x, self.yv.y, self.zv.z])
    def __str __ (self):
        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
    return Vector ([x, y, z])

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

def normalne (v1, v2, v3):
    va = v2-v1
    vb = v3-v2
    vc = v1-v3
    n1 = krzyż (va, vb)
    n2 = krzyż (vb, vc)
    n3 = krzyż (vc, va)
    return [n1, n2, n3]


def triplify (str):
    nums, triples = [], []
    dla num w str. split (''): nums + = [int (num)]
    dla i w zakresie (0, len (nums), 3):
        tróje + = [[nums [i], nums [i + 1], nums [i + 2]]]
    zwrócić trzykrotnie

verts = triplify (vertstr)
indeksy = triplify (idxstr)
nsum = Wektor ([0,0,0])
windsum = 0
xs, ys, zs = [], [], []
dla v w pionach:
    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)])
dla trójkąta we wskaźnikach:
    v1 = Wektor (verts [trójkąt [0]])
    v2 = Wektor (verts [trójkąt [1]])
    v3 = Wektor (verts [trójkąt [2]])
    normy = normalne (v1, v2, v3)
    drukuj v1, v2, v3, normy [0], normy [1], normy [2]
    dla nw normach:
        nsum + = n
    w = uzwojenie (v1, v2, v3, środek)
    drukuj „uzwojenie”, w
    jeśli w <0: windsum- = 1
    elif w> 0: windsum + = 1
if abs (windsum) == 12: print „winding ok”
w przeciwnym razie: wydrukuj „uzwojenie nie jest ok”
if (nsum.x == 0 i nsum.y == 0 i nsum.z == 0): wydrukuj „normalna suma ok”
w przeciwnym razie: wydrukuj „normalna suma nie jest ok”
Don Bright
źródło
1
Wyraźnie widać z tego przykładu, ale aby uczynić go całkowicie jednoznacznym, możesz wspomnieć, że wskaźniki są oparte na 0. To nie jest dane, ponieważ co najmniej jeden z formatów wymienionych jako przykład (OBJ) używa indeksów opartych na 1.
Reto Koradi,
To też zadziała. Myślę, że jedną z trudności w tym wyzwaniu jest to, że weryfikacja poprawności wyników jest średnio bolesna. Musisz naszkicować sześcian z wybranym porządkiem wierzchołków na kartce papieru i ręcznie sprawdzić poprawność wszystkich 12 trójkątów. Cóż, możesz napisać program sprawdzania poprawności. To może być kolejny pomysł na wyzwanie ... trudniejszy niż ten, tak myślę.
Reto Koradi,
bardzo podoba mi się pomysł innego golfa dla walidatora. zaktualizowałem przykład, aby podać pełny zestaw danych. dzięki jeszcze raz.
don bright
ok dodałem bardzo szybki i brudny program sprawdzania poprawności, który pobiera produkty krzyżowe każdej pary wektorów w każdym trójkącie, dodaje je wszystkie, a jeśli 0 mówi „ok”.
don bright

Odpowiedzi:

1

Pyth, 18 znaków

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

Ten sam pomysł, co moja odpowiedź Haskella; drukuje:

[
1
1
1
1
1
,

2
1
2
1
1
...
Lynn
źródło
Uwielbiam to, że użyłeś tego samego ciągu znaków Unicode w 3 różnych językach
don bright
1
Co to za magia jednorożca?
RK.
2

CJam, 35 bajtów

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

Wypróbuj online

Dane wyjściowe to:

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

Orientacja trójkąta jest z zewnątrz zgodna z ruchem wskazówek zegara. Sprawdziłem to ręcznie i wydaje mi się poprawne.

Wyjaśnienie:

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
źródło
To jest naprawdę fajne. . . uwielbiam symetrię ...
don bright
jest to zdecydowanie najzabawniejsza odpowiedź, ale zawiodłem definicję problemu, aby mieć opis statyczny i „brak danych wejściowych”, więc muszę zachować zgodę i przyznać najniższą liczbę znaków poniżej (co jest również zabawną odpowiedzią, ale w inny sposób), znacznik wyboru Odpowiedź. dzięki za udział.
don jasny
1

JavaScript (ES6) 78

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

Przepraszam, ale naprawdę nie rozumiem tych wyzwań bez wkładu.

edc65
źródło
przepraszam, to było moje pierwsze pytanie w golfa. Myślę, że jest już za późno, aby to zmienić teraz ...
Don Bright
Lepiej następnym razem. I tak masz mój głos.
edc65,
1

Ruby, 98 106

Naprawiono błąd wykryty przez 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(//)

Biorąc pod uwagę, że wymagane są współrzędne, jedynym sensownym schematem numeracji narożników jest ten, w którym każdy narożnik jest binarną reprezentacją jego współrzędnych. Jest to całkiem odmienne od powiązanego pytania, w którym wypróbowano różne schematy numeracji. W końcu postanowiłem wydrukować współrzędne z brudnym kodem stałym : sjest inicjowany do 000001010011100101110111ciągowej wersji 24-bitowej liczby, której reprezentacja dziesiętna to 342391. W rzeczywistości przy tej metodzie drukowania współrzędnych numeracja wierzchołków jest elastyczna, więc mogę zrób inną odpowiedź.

Okrążając równik sześcianu, znajdujemy wierzchołki 1,5, 4, 6, 2, 3, 3 i możemy zdefiniować jeden trójkąt dla każdej powierzchni z dowolnych 3 kolejnych liczb na tej liście (wracając do początku na końcu. ) Drugi trójkąt na każdej powierzchni jest zdefiniowany przez odwrócenie cyfr i zastąpienie środkowej cyfry odpowiednio 0 lub 7.

Daje to wszystkie wymagane dane wyjściowe, ale bez żadnych znaków rozdzielających. Aby to osiągnąć, po prostu konwertuję na tablicę znaków i wypisuję tablicę, tak jak poniżej (wstawiono podział linii, aby zapobiec przewijaniu):

["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
źródło
Czy jesteś pewien, że kolejność nawijania jest spójna? Na podstawie mojego szkicu 1, 5, 4jest CCW, 5, 4, 6CW.
Reto Koradi,
@RetoKoradi naprawiono na koszt 8 bajtów. Dzięki. Uświadomiłem sobie również, że lepiej mi będzie z innym schematem numeracji.
Level River St
1

Haskell, 38 znaków

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

Drukuje odpowiednie liczby, oddzielone dużą ilością śmieci:

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

Przekątna sześcianu wynosi od (1, 1, 1) do (2, 2, 2).

Lynn
źródło
1

CJam, 20 znaków

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

Ten sam pomysł, co moja odpowiedź Haskella; drukuje:

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
źródło
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]}

Pozbyłem się tego c-6, mnożąc magiczną liczbę przez 64.

Przypisanie współrzędnych jest poniżej. Dziwne, że przypisałem 100numer 1. Mogłem zapisać bajt w wersji 0, wymieniając osie i przypisując 001numer 1. Powodem tego było to, że początkowo miałem liczenie w pętli, co oznaczałoby musiał wszystko odwrócić w magicznym sznurku. W każdym razie po wprowadzonej przeze mnie zmianie nie trzeba wprowadzać żadnych dodatkowych oszczędności, więc pozostawię współrzędne bez zmian

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

Korzystanie z twardego kodowania danych współrzędnych, aby zapewnić elastyczność w wybieraniu narożników. Wyjście zawiera 54 cyfry, co oznacza, że ​​naiwne rozwiązanie miałoby 63-54 = 9 bajtów dostępnych dla kodu. Ponieważ nie mogę wymyślić sposobu wstawienia spacji w 9 bajtach, uważam, że jest to krótsze rozwiązanie niż naiwne rozwiązanie.

Schemat numeracji (na podstawie mojej odpowiedzi Ruby na powiązane pytanie https://codegolf.stackexchange.com/a/48867/15599 )

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

Wynik

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
źródło
Naprawdę podoba mi się włączenie metody @ Runer112
don bright
@donbright Byłem pierwszym, który pomyślał o umieszczeniu pierwszych 6 wierzchołków na równiku, a ostatnich 2 na biegunach w poprzednim pytaniu, dlatego moja odpowiedź C jest najbardziej popularną odpowiedzią. Miałem 6 wierzchołków w kolejności sekwencyjnej. Runer112 zasługuje na uznanie za zmianę kolejności 6 wierzchołków na równiku. Musiałem zmodyfikować kolejność twarzy dla Ruby w poprzednim pytaniu, ale kolejność wierzchołków jest rzeczywiście identyczna z kolejnością Runer112. Alternatywne uporządkowanie 6 wierzchołków na równiku przez Phinotphi dałoby mi taką samą długość w poprzednim pytaniu, ale byłoby dłuższe w tym przypadku
Level River St
wow super ... dzięki za szczegółowe wyjaśnienie ... bardzo interesujące. powinienem był pozwolić na wkład, to byłoby lepsze wyzwanie.
don bright