Stampa i vertici di un cubo e i suoi triangoli di copertura


9

Coordinate di output dei vertici di un cubo. Quindi, genera un elenco di dodici triangoli che copriranno il cubo, ogni triangolo essendo un elenco di tre indici di vertice, orientati in modo coerente. L'output deve essere una stringa ASCII di numeri decimali distinti. Questo golf non ha input. Il vincitore è il minor numero di personaggi, in cui il set di caratteri è Unicode.

Per un esempio, considera un cubo 1x1x1 messo all'angolo con 0,0,0. Gli otto vertici del cubo possono essere descritti dalle seguenti coordinate xyz su una griglia 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 ciascun vertice può essere assegnato un indice: 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

Ora considera la faccia superiore, i vertici indicizzati da zero a tre. I due triangoli di copertura possono essere descritti da tre indici ciascuno:

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

Ecco un'immagine di questa faccia superiore, vista dall'alto del cubo:

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

Ed ecco una vista da un angolo.

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

Nota che l'orientamento, o "avvolgimento", di entrambi questi triangoli è "antiorario" se visto dall'esterno del cubo guardando direttamente la faccia in questione (immagina di visitare ciascun vertice come elencato, va in senso antiorario). Ora immagina che sia fatto per tutti e sei i lati 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]

È possibile produrre qualsiasi dimensione del cubo situata in qualsiasi coordinata. Puoi numerare e ordinare le coordinate del vertice come preferisci. Gli indici possono essere basati su 0 o su 1. L'orientamento del triangolo può essere orario o antiorario se visto dall'esterno del cubo, purché sia ​​coerente per tutti i triangoli.

L'output può essere formattato come desiderato, purché ciascun numero decimale ASCII sia separato da almeno un carattere ASCII non numerico. Ad esempio, l'esempio sopra potrebbe anche essere prodotto come segue:

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

Questo golf è ispirato a vari sistemi e formati grafici 3D, tra cui OpenGL, OBJ, OFF, AMF, CGAL, ecc. Questo golf è simile al golf degli Hobby di Calvin chiamato Output a Face on a Cube numerato , la grande differenza è che hai bisogno per generare tu stesso le coordinate xyz dei vertici e per generare gli indici dei triangoli. Grazie per aver letto.

L'ispirazione per utente qui è un programma di validazione "helper" in python2 (non golfy) che stamperà "ok" o "non ok" per i dati di output del test nelle variabili vertstr e idxstr. Non funziona perfettamente ... ma può rilevare alcuni errori.

Modifica: errore di battitura corretto nell'esempio e bug nel codice di convalida.

    

#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 vettoriale:
    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 winding (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 
    ritorno d

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


def triplify (str):
    nums, triple = [], []
    per num in str.split (''): nums + = [int (num)]
    per i nell'intervallo (0, len (nums), 3):
        triple + = [[nums [i], nums [i + 1], nums [i + 2]]]
    triple di ritorno

verts = triplify (vertstr)
indici = triplifica (idxstr)
nsum = Vector ([0,0,0])
windsum = 0
xs, ys, zs = [], [], []
per v in verts:
    xs + = [v [0]]
    ys + = [v [1]]
    zs + = [v [2]]
#print xs, ys, zs, len (xs)
centro = Vector (float [(sum (xs)) / len (xs), galleggiante (sum (ys)) / len (ys), galleggiante (sum (zs)) / len (zs)])
per triangolo in indici:
    v1 = Vector (verts [triangle [0]])
    v2 = Vector (verts [triangle [1]])
    v3 = Vector (verts [triangle [2]])
    norme = normali (v1, v2, v3)
    stampa v1, v2, v3, norme [0], norme [1], norme [2]
    per n nelle norme:
        nsum + = n
    w = avvolgimento (v1, v2, v3, centro)
    stampa 'avvolgimento', w
    se w <0: windsum- = 1
    elif w> 0: windsum + = 1
if abs (windsum) == 12: stampa 'winding ok'
altro: stampa 'avvolgimento non ok'
if (nsum.x == 0 e nsum.y == 0 e nsum.z == 0): stampa 'normal sum ok'
altrimenti: stampa 'somma normale non ok'

1
È chiaro dall'esempio, ma solo per renderlo perfettamente inequivocabile, potresti voler menzionare che gli indici sono basati su 0. Questo non è un dato di fatto, poiché almeno uno dei formati elencati come esempio (OBJ) utilizza indici basati su 1.
Reto Koradi,

Funzionerà pure. Penso che una difficoltà con questa sfida sia che è moderatamente doloroso verificare la correttezza dell'output. Praticamente devi disegnare un cubo con l'ordinamento del vertice scelto su un pezzo di carta e convalidare manualmente tutti e 12 i triangoli. Bene, potresti scrivere un programma di validazione. Potrebbe essere un'altra idea di sfida ... più difficile di questa, credo.
Reto Koradi,

mi piace molto l'idea di un altro golf per un validatore. ho aggiornato l'esempio per fornire un set di dati completo. grazie ancora.
don luminoso

ok ho aggiunto un programma di validazione molto veloce e sporco che prende i prodotti incrociati di ogni coppia di vettori in ogni triangolo, li aggiunge tutti e se 0 dice 'ok'.
don luminoso

Risposte:


1

Pyth, 18 personaggi

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

Stessa idea della mia risposta Haskell; stampe:

[
1
1
1
1
1
,

2
1
2
1
1
...

mi piace che tu abbia usato la stessa stringa unicode in 3 lingue diverse
don luminoso

1
Cos'è questa magia unicode?
RK.

2

CJam, 35 byte

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

Provalo online

L'output è:

[[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'orientamento del triangolo è in senso orario dall'esterno. L'ho controllato manualmente e mi sembra corretto.

Spiegazione:

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.

è davvero bello. . . Adoro la simmetria ...
don luminoso

questa è chiaramente la risposta più divertente, ma ho incasinato la mia definizione del problema per avere una descrizione statica e "nessun input", quindi devo mantenere l'accordo e assegnare il conteggio dei caratteri più basso, di seguito (che è anche una risposta divertente ma in un modo diverso), il segno di spunta Risposta. grazie per aver partecipato.
don luminoso

1

JavaScript (ES6) 78

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

Scusa ma non capisco davvero queste sfide senza input.


scusa, è stata la mia prima domanda sul golf. immagino sia troppo tardi per cambiarlo ora ...
don luminoso

Meglio la prossima volta. Hai comunque il mio voto.
edc65,

1

Ruby, 98 106

Risolto errore rilevato da 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(//)

Dato che sono necessarie le coordinate, l'unico schema di numerazione degli angoli che aveva senso sembrava essere quello in cui ogni angolo è la rappresentazione binaria delle sue coordinate. È abbastanza diverso dalla domanda collegata, in cui sono stati provati vari schemi di numerazione diversi. Alla fine ho deciso di stampare le coordinate con un hardcode sporco: sviene inizializzato alla versione stringa del numero di 24 bit la 000001010011100101110111cui rappresentazione decimale è 342391. In realtà con questo metodo di stampa delle coordinate, la numerazione dei vertici è flessibile, quindi potrei fai un'altra risposta.

Girando intorno all'equatore del cubo, troviamo i vertici 1,5,4,6,2,3 e possiamo definire un triangolo per ogni faccia da qualsiasi 3 numeri consecutivi in ​​questo elenco (tornando all'inizio alla fine. ) L'altro triangolo su ciascuna faccia viene definito invertendo le cifre e sostituendo la cifra centrale con 0 o 7, a seconda dei casi.

Ciò fornisce tutto l'output richiesto, ma senza caratteri di separazione. A tale scopo, converto semplicemente in una matrice di caratteri e stampo la matrice, in questo modo (interruzioni di riga inserite per impedire lo scorrimento):

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

Sei sicuro che l'ordine degli avvolgimenti sia coerente? Sulla base del mio schizzo, 1, 5, 4è CCW, 5, 4, 6è CW.
Reto Koradi,

@RetoKoradi risolto al costo di 8 byte. Grazie. Inoltre, ho capito che potrei fare di meglio con un diverso schema di numerazione.
Level River St

1

Haskell, 38 personaggi

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

Stampa i numeri giusti, separati da un sacco di spazzatura:

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

La diagonale del cubo va da (1, 1, 1) a (2, 2, 2).


1

CJam, 20 caratteri

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

Stessa idea della mia risposta Haskell; stampe:

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

Mi sono sbarazzato di c-6moltiplicando il numero magico per 64.

L'assegnazione delle coordinate è di seguito. È strano che abbia assegnato 100al numero 1. Avrei potuto salvare un byte in rev 0 scambiando gli assi e assegnando 001al numero 1. Il motivo era quello perché in origine avevo il conteggio nel loop, il che avrebbe significato dovevo mettere tutto al contrario nella corda magica. Ad ogni modo, con la modifica che ho apportato ora, non è necessario effettuare ulteriori risparmi, quindi lascerò le coordinate così come sono

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

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

Utilizzo dell'hardcoding dei dati delle coordinate per dare flessibilità nella scelta degli angoli. Ci sono 54 cifre nell'output, il che significa che la soluzione ingenua avrebbe 63-54 = 9 byte disponibili per il codice. Poiché non riesco a pensare a un modo per inserire spazi in 9 byte, credo che questo sia più breve della soluzione ingenua.

Schema di numerazione (adattato dalla mia risposta di Ruby alla domanda collegata https://codegolf.stackexchange.com/a/48867/15599 )

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

Produzione

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]

Mi piace molto l'incorporazione del metodo di @ Runer112
don luminoso

@donbright Sono stato il primo a pensare di mettere i primi 6 vertici sull'equatore e gli ultimi 2 sui poli in quella domanda precedente, motivo per cui la mia risposta in C è la risposta più popolare. Ho avuto i 6 vertici in ordine sequenziale. Runer112 merita un po 'di credito per il suo riordino dei 6 vertici sull'equatore. Ho dovuto modificare l'ordine dei volti per Ruby sulla domanda precedente, ma l'ordine dei vertici è davvero identico a quello di Runer112. Il riordino alternativo di Phinotphi dei 6 vertici sull'equatore mi avrebbe dato la stessa lunghezza sulla domanda precedente, ma sarebbe più lungo su questo
Level River St

wow fantastico ... grazie per la spiegazione dettagliata ... molto interessante. avrei dovuto permettere un input, quindi sarebbe stata una sfida migliore.
don luminoso
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.