Надрукуйте вершини куба та його покривні трикутники


9

Виведіть координати вершин куба. Потім виведіть список з дванадцяти трикутників, які будуть охоплювати куб, кожен трикутник - це список трьох вершин-індексів, послідовно орієнтованих. Вихід повинен бути рядком ASCII різних десяткових чисел. Цей гольф не має жодної інформації. Переможець - найменше символів, де набір символів - Unicode.

Для прикладу розглянемо куб 1x1x1, закручений кутом 0,0,0. Вісім вершин куба можна описати наступними координатами xyz на 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)

Кожній вершині може бути призначений індекс: 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

Тепер розглянемо верхню грань, вершини з індексом нуля до трьох. Два трикутники, що охоплюють, можна описати трьома індексами кожен:

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

Ось фотографія цього верхнього обличчя, видно зверху куба:

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

І ось погляд з кута.

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

Зауважте, що орієнтація або "звивистість" обох цих трикутників є "проти годинникової стрілки", коли дивитися "зовні" куба, безпосередньо дивлячись на відповідне обличчя (уявіть, що ви відвідуєте кожну вершину, як зазначено, вона йде проти годинникової стрілки). А тепер уявіть, що це зроблено для всіх шести сторін куба.

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]

Ви можете вивести будь-який розмір куба, розташованого в будь-яких координатах. Ви можете нумерувати та замовляти вершинні координати, за бажанням. Індекси можуть бути 0 або 1. Орієнтація трикутника може бути як за годинниковою стрілкою, так і проти годинникової стрілки, якщо дивитися ззовні куба, якщо це відповідає всім трикутникам.

Вихід може бути відформатований як завгодно, якщо кожне десятичне число ASCII розділено принаймні одним нечисловим символом ASCII. Наприклад, наведений вище приклад також може бути виведений наступним чином:

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

Це гольф натхненний різними 3D - графічних систем і форматів, включаючи OpenGL, OBJ, OFF, AMF, CGAL і т.д. Це гольф схожий на гольф по хобі Кальвіна по імені Виведіть особи на нумерованому куб , велика різниця в тому , що вам потрібно самому вивести координати xyz вершин і вивести індекси трикутника. Дякуємо за прочитане

Натхнення користувача тут - програма перевірки "помічників" в python2 (non-golfy), яка буде друкувати "ok" або "not ok" для тестових вихідних даних у змінних vertstr та idxstr. Це не працює ідеально ... але це може привести до деяких помилок.

Редагувати: виправлена ​​помилка в прикладі та помилки в коді перевірки.

    

#vertstr = '0 0 0 0 0 1 0 1 0 0 1 1 1 0 0 1 0 1 1 0 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'

вектор класу:
    def __init __ (self, v):
        self.x, self.y, self.z = v [0], v [1], v [2]
    def __add __ (self, v):
        повернути вектор ([self.x + vx, self.y + vy, self.z + vz])
    def __sub __ (self, v):
        повернути вектор ([self.xv.x, self.yv.y, self.zv.z])
    def __str __ (само):
        повернути str (self.x) + ',' + str (self.y) + ',' + str (self.z)

дефрест (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
    повернути вектор ([x, y, z])

# http://mathforum.org/library/drmath/view/55343.html & http://sympy.org
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. х, 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 
    повернути d

стандартні значення def (v1, v2, v3):
    va = v2-v1
    vb = v3-v2
    vc = v1-v3
    n1 = хрест (va, vb)
    n2 = хрест (vb, vc)
    n3 = хрест (vc, va)
    повернення [n1, n2, n3]


def помножити (str):
    nums, triples = [], []
    для num in str.split (''): nums + = [int (num)]
    для i в діапазоні (0, len (nums), 3):
        трійки + = [[nums [i], nums [i + 1], nums [i + 2]]]
    повернути трійки

verts = помножити (vertstr)
індекси = помножити (idxstr)
nsum = вектор ([0,0,0])
вітрова = 0
xs, ys, zs = [], [], []
для v у вертах:
    xs + = [v [0]]
    ys + = [v [1]]
    zs + = [v [2]]
#print xs, ys, zs, len (xs)
центр = вектор ([float (сума (xs)) / len (xs), float (sum (ys)) / len (ys), float (sum (zs)) / len (zs)])
для трикутника в індексах:
    v1 = вектор (верти [трикутник [0]])
    v2 = вектор (верти [трикутник [1]])
    v3 = вектор (верти [трикутник [2]])
    норми = нормальні (v1, v2, v3)
    print v1, v2, v3, норми [0], норми [1], норми [2]
    для n в нормах:
        nsum + = n
    w = обмотка (v1, v2, v3, центр)
    друкувати ‘намотування’, ж
    якщо w <0: вітра- = 1
    elif w> 0: вітрове + = 1
if abs (windum) == 12: надрукувати "обмотка нормально"
інше: надрукувати "намотування не нормально"
якщо (nsum.x == 0 і nsum.y == 0 і nsum.z == 0): надрукувати "звичайну суму нормально"
інше: надрукувати "звичайну суму не нормально"

1
З прикладу це зрозуміло, але для того, щоб зробити це абсолютно однозначним, ви можете сказати, що показники базуються на 0. Це не дано, оскільки принаймні один із форматів, які ви перераховуєте як приклад (OBJ), використовує 1-базисні індекси.
Ретро Кораді

Це також спрацює. Я думаю, що одна проблема з цим завданням полягає в тому, що перевірити правильність результатів досить помітно. Ви майже повинні намалювати кубик із вибраним упорядком вершини на аркуші паперу та вручну підтвердити всі 12 трикутників. Ну, ви могли б написати програму перевірки. Насправді це може бути ще одна складна ідея ... Я думаю, складніше, ніж ця.
Ретро Коради

мені дуже подобається ця ідея іншого гольфу для валідатора. я оновив приклад, щоб отримати повний набір даних. знову дякую.
дон світлий

Ок, я додав дуже швидку та брудну програму перевірки, яка бере перехресні продукти кожної пари векторів у кожному трикутнику, додає їх усі, і якщо 0 каже «добре».
нехай яскраво

Відповіді:


1

Піта, 18 символів

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

Та сама ідея, що і моя відповідь Haskell; відбитки:

[
1
1
1
1
1
,

2
1
2
1
1
...

мені подобається, що ти використовував одну і ту ж рядок Unicode на трьох різних мовах
нехай яскраво

1
Що це за магія Unicode?
РК.

2

CJam, 35 байт

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

Спробуйте в Інтернеті

Вихід:

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

Орієнтація трикутника знаходиться за годинниковою стрілкою зовні. Я перевірив це вручну, і мені це виглядає правильно.

Пояснення:

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.

це дійсно круто. . . люблю симетрію ...
нехай яскраво

це, очевидно, найсмішніша відповідь, але я зіпсував своє визначення проблеми, щоб мати статичний опис і "не вводити", тому я повинен зберігати угоду і присвоювати найнижчу кількість символів внизу (що також є цікавою відповіддю, але в по-різному), галочка Відповідь. дякую за участь
дон світлий

1

JavaScript (ES6) 78

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

Вибачте, але я справді не розумію цих проблем без будь-яких вкладів.


вибачте, це було моє перше питання про гольф. я здогадуюсь, що зараз це занадто пізно змінити ...
нехай яскраво

Краще наступного разу. Ви все одно маєте мій голос.
edc65

1

Рубі, 98 106

Виправлена ​​помилка, яку помітив Рето Кораді.

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

Зважаючи на те, що координати потрібні, єдиною схемою нумерації кутів, яка мала сенс, здавалася, є та, де кожен кут - це двійкове представлення його координат. Це зовсім відрізняється від пов'язаного питання, де були випробувані різні схеми нумерації. Врешті-решт я вирішив надрукувати координати брудним жорстким кодом: sініціалізується на 000001010011100101110111рядкову версію 24-бітного числа , десяткове представлення якого 342391. Насправді при такому способі друку координат нумерація вершин є гнучким, тому я можу зробіть іншу відповідь.

Обходячи екватор куба, ми знаходимо вершини 1,5,4,6,2,3 і можемо визначити по одному трикутнику для кожної грані з будь-яких 3-х підрядних чисел у цьому списку (повернення до початку наприкінці. ) Інший трикутник на кожній грані визначається шляхом обернення цифр і заміщення середньої цифри на 0 або 7, якщо це доречно.

Це дає всі необхідні результати, але без жодних розділювальних символів. Для цього я просто перетворюю на масив символів і друкую масив, як це (вставки вставлені для запобігання прокручування):

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

Ви впевнені, що порядок обмотки відповідає? На основі мого ескізу, 1, 5, 4це CCW, 5, 4, 6це CW.
Рето Кораді

@RetoKoradi фіксується вартістю 8 байт. Дякую. Крім того, я зрозумів, що я можу краще зробити іншу схему нумерації.
Рівень р. Св.

1

Хаскелл, 38 символів

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

Друкує правильні цифри, розділені цілою кількістю сміття:

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

Діагональ куба - від (1, 1, 1) до (2, 2, 2).


1

CJam, 20 символів

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

Та сама ідея, що і моя відповідь Haskell; відбитки:

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

Рубі, Рев. 1 62

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

Позбувся від c-6множення магічного числа на 64.

Призначення координат знаходиться нижче. Дивно, що я призначив 100номер 1. Я міг би зберегти байт у rev 0, обмінявши осі та призначивши 001номер 1. Причиною цього було саме тому, що спочатку я мав підрахунок у циклі, що означало б, що я довелося покласти все зворотно в чарівну струну. У будь-якому випадку, із зміною, яку я вніс зараз, додаткового збереження не потрібно робити, тому я залишу координати такими, якими вони є

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

Рубі, Рев. 0 63

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

Використання жорсткого кодування даних координат для забезпечення гнучкості у виборі кутів. На виході є 54 цифри, це означає, що наївне рішення матиме 63-54 = 9 байт для коду. Оскільки я не можу придумати спосіб вставити пробіли в 9 байт, я вважаю, що це коротше, ніж наївне рішення.

Схема нумерації (адаптована з моєї відповіді Ruby на пов'язане питання https://codegolf.stackexchange.com/a/48867/15599 )

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

Вихідні дані

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]

Мені дуже подобається інкорпорація @ методу Runer112 «s
одягає яскравий

@donbright Я першим подумав поставити перші 6 вершин на екваторі та останні 2 на полюсах у тому попередньому запитанні, саме тому моя відповідь С - найпопулярніша відповідь. У мене було 6 вершин у послідовному порядку. Runer112 заслуговує певної заслуги на переупорядкування 6 вершин на екваторі. Я повинен був змінити порядок обличчя для Рубі в попередньому питанні, але порядок вершин дійсно ідентичний Runer112. Альтернативне переупорядкування 6 вершин на екваторі дало б мені рівну довжину в попередньому питанні, але було б довше за цим
Річка рівня Св.

вау дивним ... дякую за детальне пояснення ... дуже цікаво. я мав би дозволити введення, тоді це було б кращим завданням.
нехай яскравий
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.