Распечатать вершины куба и его покрывающие треугольники


9

Выходные координаты вершин куба. Затем выведите список из двенадцати треугольников, которые будут покрывать куб, причем каждый треугольник представляет собой список из трех индексов вершин, последовательно ориентированных. Выход должен быть строкой ASCII с различными десятичными числами. Этот гольф не имеет ввода. Победитель - это наименьшее количество символов, где набор символов - Unicode.

Для примера рассмотрим куб 1x1x1 с углом 0,0,0. Восемь вершин куба можно описать следующими координатами xyz на трехмерной декартовой сетке:

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

Этот гольф вдохновлен различными системами и форматами трехмерной графики, включая OpenGL, OBJ, OFF, AMF, CGAL и т. Д. Этот гольф похож на гольф от хобби Calvin's по имени Вывести лицо на пронумерованном кубе , большая разница в том, что вам нужно вывести координаты xyz вершин самостоятельно и вывести индексы треугольника. Спасибо за чтение.

Вдохновением для пользователя здесь является «вспомогательная» программа проверки в python2 (не для гольфа), которая выведет «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 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'

Вектор класса:
    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 __ (self):
        вернуть 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
    Вектор возврата ([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, х3, у3, г3, 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 
    возврат г

нормальные значения (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 triplify (str):
    НУМС, тройки = [], []
    для num в str.split (''): nums + = [int (num)]
    для i в диапазоне (0, len (nums), 3):
        тройки + = [[nums [i], nums [i + 1], nums [i + 2]]]
    обратные тройки

verts = triplify (vertstr)
индексы = трижды (idxstr)
nsum = Vector ([0,0,0])
windsum = 0
Xs, YS, ZS = [], [], []
для v в вертах:
    хз + = [v [0]]
    YS + = [v [1]]
    ZS + = [v [2]]
# напечатайте xs, ys, zs, len (xs)
центр Вектор = ([с плавающей точкой (сумма (XS)) / LEN (XS), поплавок (сумма (YS)) / LEN (YS), поплавок (сумма (ZS)) / LEN (ZS)])
для треугольника в индексах:
    v1 = вектор (verts [треугольник [0]])
    v2 = вектор (verts [треугольник [1]])
    v3 = Vector (verts [треугольник [2]])
    нормы = нормальные (v1, v2, v3)
    print v1, v2, v3, нормы [0], нормы [1], нормы [2]
    в нормах:
        nsum + = n
    w = обмотка (v1, v2, v3, центр)
    печать "намотка", ш
    если w <0: windsum- = 1
    elif w> 0: windsum + = 1
если abs (windsum) == 12: выведите «winding ok»
еще: выведите «намотка не в порядке»
if (nsum.x == 0 и nsum.y == 0 и nsum.z == 0): выведите 'normal sum ok'
иначе: выведите «нормальная сумма не в порядке»

1
Это видно из примера, но просто чтобы сделать его совершенно однозначным, вы можете упомянуть, что индексы основаны на 0. Это не дано, так как по крайней мере один из форматов, которые вы перечислите в качестве примера (OBJ), использует индексы на основе 1.
Рето Коради

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

мне действительно нравится эта идея другого гольфа для валидатора. я обновил пример, чтобы дать полный набор данных. еще раз спасибо.
Дон

Хорошо, я добавил очень быструю и грязную программу проверки, которая берет перекрестные произведения каждой пары векторов в каждом треугольнике, добавляет их все, и если 0 говорит «хорошо».
Дон

Ответы:


1

Pyth, 18 знаков

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

Та же идея, что и в моем ответе на Haskell; печатает:

[
1
1
1
1
1
,

2
1
2
1
1
...

Мне нравится, что вы использовали одну и ту же строку Unicode на 3 разных языках
Don

1
Что это за магия юникода?
РК.

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инициализируется строковой версией 24-битного числа 000001010011100101110111, десятичное представление которого равно 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 байт. Спасибо. Кроме того, я понял, что могу добиться большего успеха с другой схемой нумерации.
Уровень Река St

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

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

Избавился от c-6умножения магического числа на 64.

Назначение координат ниже. Странно, что я присвоил 100номер 1. Я мог бы сохранить байт в рев. 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

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

Использование жесткого кодирования данных координат для обеспечения гибкости при выборе углов. В выводе содержится 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
наденьте светлый

@donbright Я был первым, кто подумал о размещении первых 6 вершин на экваторе и последних двух на полюсах в этом предыдущем вопросе, поэтому мой ответ на C является самым популярным ответом. У меня было 6 вершин в последовательном порядке. Runer112 заслуживает некоторой похвалы за переупорядочение 6 вершин на экваторе. Мне пришлось изменить порядок граней для Ruby в предыдущем вопросе, но порядок вершин действительно идентичен порядку Runer112. Альтернативное переупорядочение Phinotphi 6 вершин на экваторе дало бы мне равную длину в предыдущем вопросе, но было бы больше в этом
Level River St

вау круто ... спасибо за подробное объяснение ... очень интересно. я должен был позволить ввод, тогда это было бы лучшим испытанием.
Дон Яркий
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.