크리스마스 스타 그리기 / 별 이십 면체


10

크리스마스에는 가족에게 종이 별이 큰 것이기 때문에 가상의 별이 시원 할 것이라고 생각했습니다.

아래는 정기 십이 면체 의 이미지입니다 ( https://en.wikipedia.org/wiki/Dodecahedron ).

여기에 이미지 설명을 입력하십시오

다면체에 적용될 때 별자리 과정 (wikipedia)은 다른면과 교차 할 때까지면을 연장하는 것을 포함합니다. 따라서 정 십이 면체로 시작하여 다음과 같은 모양을 얻습니다.

작은 별 십이 면체, 큰 십이 면체 및 큰 별 십이 면체

http://jwilson.coe.uga.edu/emat6680fa07/thrash/asn1/stellations.html의 이미지

여기에 이미지 설명을 입력하십시오

이들은 십이 면체 (Wolfram) 의 세 가지 가능한 설명입니다 . 그들은 우리가 얼굴을 더 그리고 더 확장함에 따라 십이 면체에서 작은 별 모양 십이 면체, 큰 십이 면체 및 큰 별 모양 십이 면체로 자연스럽게 진행된다.

직무

프로그램 또는 함수는 일반 다면체 , 작은 별 모양 십이 면체, 큰 십이 면체 또는 위대한 성 십이 면체 중 하나의 이미지 파일로 표시하거나 출력해야합니다 .

색 구성표는 위의 두 번째 이미지와 같아야합니다. 6 쌍의 반대면은 각각 빨강, 노랑, 녹색, 청록, 파랑, 마젠타의 6 가지 색상 중 하나입니다. 언어 또는 설명서에 이러한 이름의 기본 색상을 사용하거나 FF0000, FFFF00, 00FF00, 00FFFF, 0000FF 및 FF00FF 색상을 사용할 수 있습니다 (원하는 경우 강도를 최소 75 %로 줄여 톤을 낮출 수 있음, 예를 들어 F를 C로 줄임으로써)

"평면"을 동일한 평면의 모든 영역으로 정의합니다. 따라서 앞면 위의 이미지는 노란색입니다 (평행 한 뒷면도 노란색입니다).

배경은 검은 색, 회색 또는 흰색이어야합니다. 가장자리는 생략 할 수 있지만 그려진 경우 검은 색이어야합니다.

규칙

표시된 다면체의 너비는 500-1000 픽셀이어야합니다 (너비는 표시된 두 정점 사이의 최대 거리로 정의 됨).

표시된 다면체는 투시 투영 (다면체로부터 5 폭 이상 떨어진 시점) 또는 직교 투영 (유효한 시점을 가진 투시 투영)에 있어야합니다.

다면체는 어느 각도에서나 표시 할 수 있어야합니다. (가장 쉬운 각도를 선택하고 하드 코딩 된 2D 모양을 만드는 것은 허용되지 않습니다.) 각도는 다음 방법 중 하나로 사용자가 지정할 수 있습니다.

  1. stdin에서 또는 함수 또는 명령 줄 매개 변수로 3 개의 회전에 해당하는 3 개의 각도 입력 오일러 각도 (첫 번째 회전과 마지막 회전이 같은 축을 중심으로하는 위치) 또는 Tait-Bryan 각도 (각각 x, y 및 z 축을 중심으로 한 회전이있는 위치) https://en.wikipedia.org/ wiki / Euler_angles (간단히 말하면, 각 회전이 x, y 또는 z 축에 대해 있고 연속 회전이 수직 축에 관한 한 모든 것이 진행됩니다.)

  2. 사용자가 x 축과 y 축을 중심으로 다면체를 10도 이상 회전하지 않고 임의의 횟수로 화면을 새로 고치는 기능 (화면에 수직 인 z 축을 가정).

다면체는 와이어 프레임이 아닌 단단해야합니다.

다면체 그리기를위한 내장은 허용되지 않습니다 (Mathematica를보고 있습니다).

채점

이것은 codegolf입니다. 바이트 단위의 최단 코드가 이깁니다.

보너스

3D 드로잉에 내장을 사용하지 않는 경우 점수에 0.5를 곱하십시오.

십이 면체의 별자리 3 개를 모두 표시 할 수 있으면 stdin에서 입력 한 정수 1-3 또는 함수 또는 명령 줄 매개 변수로 사용자가 선택할 수있는 경우 점수에 0.7을 곱하십시오.

두 보너스를 모두 받으면 점수에 0.5 * 0.7 = 0.35가 곱해집니다.

유용한 정보 (아래와 같은 출처)

https://en.wikipedia.org/wiki/Regular_dodecahedron

https://en.wikipedia.org/wiki/Regular_icosahedron

정 십이 면체에는 20 개의 정점이 있습니다. 그 중 8 개는 다음과 같은 직교 좌표 (x, y, z)를 사용하여 큐브의 정점을 형성합니다.

(± 1, ± 1, ± 1)

나머지 12 개는 다음과 같습니다 (phi는 황금 비율 임).

(0, ± 1 / φ, ± φ)

(± 1 / φ, ± φ, 0)

(± φ, 0, ± 1 / φ)

작은 별 모양 십이 면체와 큰 십이 면체의 볼록 껍질은 분명히 규칙적인 십이 면체입니다. 바깥 쪽 정점은 정 이십 면체를 나타냅니다.

Wikipedia에 따르면 정 이십 면체의 12 정점은 (0, ± 1, ± φ)의 순환 순열과 유사한 방식으로 설명 될 수 있습니다. 작은 별 모양 십이 면체와 큰 십이 면체 (위의 십이 면체와 같은 규모)의 외부 정점은 더 큰 정 이십 면체를 형성하며, 정점의 좌표는 (0, ± φ ^ 2, ± φ)의 순환 순열입니다.

정 십이 면체와 정 이십 면체의면 사이의 각도는 각각 2 arctan (phi) 및 arccos (-(√5) / 3)입니다.

회전에 대한 팁은 https://en.wikipedia.org/wiki/Rotation_matrix를 참조 하십시오.

편집 : 실수로 일반 정 십이 면체를 허용했으며 지금 철회 할 수 없습니다. 별 모양의 다면체를 모두 그리는 데 사용되는 x0.7 보너스가 남아 있습니다. 새해 첫날에는 네 개의 다면체를 최대한 표시하고 가장 짧은 코드를 타이 브레이크로 표시 할 수있는 현상금 100을 지급합니다.


다면체 (예 :)를 그리기위한 @ LegionMammal978 내장 dodecahedron은 허용되지 않습니다. 일부 언어에는와 같은 명령으로 3D 모델을 구축 할 수있는 기능이 있습니다 triangle[[a,b,c],[p,q,r],[x,y,z]]. 이러한 언어에는 일반적으로 모델 회전 및 표시를위한 내장 기능이 있으며 숨겨진 얼굴 등을 자동으로 표시하지 않습니다. 이러한 언어와 같은 솔루션은 허용되지만 보너스를받지는 않습니다. 보너스의 목적은 이러한 시설이없는 언어의 경쟁력을 높이고보다 흥미로운 해결책을 찾는 것입니다.
Level River St

@ LegionMammal978 haha, Mathematica가 문제를 일으키는 언어라는 것을 알고있었습니다. Polyhedrondata다면체 그리기를위한 내장 기능이 명확하지 않으므로 허용되지 않습니다. 답이 다면체를 그리기 위해 내장을 사용하지 않고 다른 규칙을 준수하는 경우 허용됩니다. 당신의 요점은 얼굴을 올바르게 채색해야한다는 사실을 감안할 때 Polyhedrondata어쨌든 많이 절약하지 못하기 때문에 실제로 다소 임의의 제한이있을 수 있습니다. 어느 정도 동의하지만 게시 후 규칙을 변경하지 않으면 모든 것이 더 공정합니다.
Level River St

답변:


3

파이썬 2.7, 949 바이트

다음은 matplotlib을 사용하여 정점 십이 면체에 대한 솔루션입니다. ungolfed 코드 (여기에 표시되지 않음)의 대략적인 개요는 다음과 같습니다.

  • 정점 만들기 모서리 만들기 (가장 가까운 이웃 3 개, 모듈 scipy.spatial.KDtree 기준)
  • 길이가 5 인 그래프주기를 기준으로면 만들기 (모듈 networkx)
  • 면 법선을 만듭니다 (그리고 바깥 쪽을 향하는 법선, numpy.cross를 가진 것을 선택하십시오)
  • 얼굴 법선을 기반으로 색상 생성
  • matplotlib을 사용하여 플로팅
import itertools as it
import numpy as np
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
import matplotlib.pyplot as plt
v=[p for p in it.product((-1,1),(-1,1),(-1,1))]
g=.5+.5*5**.5
v.extend([p for p in it.product((0,),(-1/g,1/g),(-g,g))])
v.extend([p for p in it.product((-1/g,1/g),(-g,g),(0,))])
v.extend([p for p in it.product((-g,g),(0,),(-1/g,1/g))])
v=np.array(v)
g=[[12,14,5,9,1],[12,1,17,16,0],[12,0,8,4,14],[4,18,19,5,14],[4,8,10,6,18],[5,19,7,11,9],[7,15,13,3,11],[7,19,18,6,15],[6,10,2,13,15],[13,2,16,17,3],[3,17,1,9,11],[16,2,10,8,0]]
a=[2,1,0,3,4,5,0,1,2,3,4,5]
fig = plt.figure()
ax = fig.add_subplot((111),aspect='equal',projection='3d')
ax.set_xlim3d(-2, 2)
ax.set_ylim3d(-2, 2)
ax.set_zlim3d(-2, 2)
for f in range(12):
 c=Poly3DCollection([[tuple(y) for y in v[g[f],:]]], linewidths=1, alpha=1)
 c.set_facecolor([(0,0,1),(0,1,0),(0,1,1),(1,0,0),(1,0,1),(1,1,0)][a[f]])
 ax.add_collection3d(c)
ax.auto_scale_xyz
plt.show()

여기에 이미지 설명을 입력하십시오


3

루비, 784 바이트 * 0.5 * 0.7 = 274.4

내 자신의 답변, 따라서 내 현상금을받을 수 없습니다.

3D가 아닌 내장 보너스와 모든 스텔 레이션 보너스를받을 수 있습니다.

->t,n{o=[]
g=->a{a.reduce(:+)/5}
f=->u,v,w,m{x=u.dup;y=v.dup;z=w.dup
15.times{|i|k,l=("i".to_c**(n[i/5]/90.0)).rect
j=i%5
x[j],y[j],z[j]=y[j],x[j]*k+z[j]*l,z[j]*k-x[j]*l}
p=g[x];q=g[y];r=g[z]
a=[0,1,-i=0.382,-1][t]*e=r<=>0
b=[j=1+i,0,j,j][t]*e
c=[-i*j,-i,1,i][t]*e
d=[j*j,j,0,0][t]*e
5.times{|i|o<<"<path id=\"#{"%9.0f"%(z[i]*a+r*b+(z[i-2]+z[i-3])*c+2*r*d+999)}\"
d=\"M#{(x[i]*a+p*b)} #{(y[i]*a+q*b)}L#{(x[i-2]*c+p*d)} #{(y[i-2]*c+q*d)}L#{(x[i-3]*c+p*d)} #{(y[i-3]*c+q*d)}\"
fill=\"##{m}\"/>"}}
a=233
b=377
z=[0,a,b,a,0]
y=[a,b,0,-b,-a]
x=[b,0,-a,0,b]
w=[-b,0,a,0,-b]
f[x,y,z,'F0F']
f[w,y,z,'0F0']
f[y,z,x,'00F']
f[y,z,w,'FF0']
f[z,x,y,'F00']
f[z,w,y,'0FF']
s=File.open("p.svg","w")
s.puts'<svg xmlns="http://www.w3.org/2000/svg" viewBox="-450 -450 900 900">',o.sort,'</svg>'
s.close}

기능 매개 변수로 입력

정규 십이 면체, 작은 별 모양 십이 면체, 큰 별 모양 십이 면체에 해당하는 정수 0..3

x, y 및 x (다시) 축 주위의 회전 각도 각도에 해당하는 세 개의 정수 배열 (적절한 오일러 각도, 회전이 가능하도록합니다.)

p.svg웹 브라우저에 표시 할 수 있는 파일 을 출력 하십시오 .

설명

코드 하단의 배열 x, y, z는 작은 별 모양 십이 면체의 한면의 외부 점 좌표를 포함합니다. 이것은 12 개의 정점이 (+/- 377, + /-233, + /-0)의 순환 순열로 정의 된 정 이십 면체에 새겨질 수 있습니다. 377과 233은 연속적인 피보나치 수이므로 377/233은 황금 비율에 대한 훌륭한 근사치입니다.

추가 배열 w에는 x 좌표에 -1을 곱한 x 좌표가 포함되어 있으며 x 평면에서의 반사와 같습니다. 함수 f는 x, y, z 및 w, y, z의 서로 다른 순환 순열을 사용하여 각 색상마다 한 번씩 6 번 호출됩니다.

3 개의 회전은 n []의 매개 변수로 전달됩니다. Ruby에서 sin과 cos를 사용하려면을 수행해야 include Math합니다. 이를 피하기 위해 각도의 코사인과 사인은 -1의 제곱근을 (제곱 "i"각도 / 90)의 제곱으로 올리면 얻을 수 있습니다.이 수의 실수 부와 허수 부는 k (코사인)와 l ( 사인)

회전하기 전에 x와 y 값이 교환됩니다. 그런 다음 행렬 곱셈이 y 및 z 값에 적용되어 x 축을 중심으로 회전합니다. 값을 교환하면 세 개의 회전을 루프로 수행 할 수 있습니다.

지금까지 하나의 링만 있습니다. 나머지를 얻으려면 오각형 / 별의 중심을 찾아야합니다. 이것은 p, q, r에 저장된 5 개의 꼭짓점의 평균 좌표를 찾아서 수행됩니다.

앞에서 언급했듯이 색상 당 하나의 함수 호출 만 수행됩니다. r의 부호 (z 좌표의 평균, 따라서면의 좌표)가 테스트됩니다. 양수이면면이 정면이므로 표시됩니다. 음수이면면이 후면입니다. 그것은 보이지 않으며 반대면을위한 함수 호출이 없습니다. 따라서 세 좌표가 모두 반전되어야합니다. r의 부호는이를 용이하게하기 위해 e에 저장됩니다.

면은 5 개의 삼각형으로 구성되며, 정점은 작은 별 모양 십이 면체의 바깥 쪽 정점과면의 중심의 선형 조합입니다. 작은 별 모양 십이 면체의 경우, 삼각형의 끝을 위해 우리는 a = 1과 b = 0 (x, y, z의 기여도 1과 p, q, r의 기여도 1)을 설정했습니다. 삼각형의 두 기본 정점에 대해 c = -0.382 (x, y, z의 기여도 1 / 황금 비율 ^ 2)와 d = 1.382 (p, q, r의 기여도)를 설정했습니다. 삼각형의 기저 정점은 반대편 팁의 측면에서 정의되며면의 반대쪽에 있습니다. 얻어진 좌표에 필요에 따라 e를 곱한다.

그 값이 할당되는 네 이름 배열 a,b,c,d변수에 따라 선택 정규 면체, 작은 별 모양 십이 면체 큰 면체와 큰 별 모양 십이 면체 대한 필요한 값을 포함 t하는 것으로 작은 별 모양의 면체 큰 면체위한 + B = C + d = 1. 관계 a + b = c + d는 다른 모양에 적용되지만 다른 축척이 적용됩니다.

각 삼각형마다 svg 코드 줄이 만들어집니다. 여기에는 삼각형의 3 개의 정점의 z 좌표, 삼각형의 3 개의 좌표의 정점 및 색상의 합계에서 파생 된 ID가 포함됩니다. 직교 투영에서 z 축을 똑바로 봅니다. 따라서 2D x = 3D x 및 2D y = 3D y입니다. 라인이 추가됩니다h.

마지막으로 모든 함수 호출이 완료되면 h가 정렬되어 z 값이 가장 높은 삼각형 (앞)이 마지막에 그려지고 모든 것이 적절한 머리글과 바닥 글 텍스트와 함께 svg 파일로 저장됩니다.

테스트 프로그램에서 언 골프

h=->t,n{                                              #t=type of polygon,n=angles of rotation
o=[]                                                  #array for output
g=->a{a.reduce(:+)/5}                                 #auxiliary function for finding average of 5 points

f=->u,v,w,m{x=u.dup;y=v.dup;z=w.dup                   #function to take 5 points u,v,w and plot one face (5 triangles) of the output in colour m 

  15.times{|i|                                        #for each of 3 rotation angle and 5 points
    k,l=("i".to_c**(n[i/5]/90.0)).rect                #calculate the cos and sine of the angle, by raising sqrt(-1)="i" to a power
    j=i%5                                             #for each of the 5 points
    x[j],y[j],z[j]=y[j],x[j]*k+z[j]*l,z[j]*k-x[j]*l}  #swap x and y, then perform maxtrix rotation on (new) y and z.

  p=g[x];q=g[y];r=g[z]                                #find centre p,q,r of the face whose 5 points (in the case of small stellated dodecahedron) are in x,y,z

  e=r<=>0                                             #if r is positive, face is front. if negative, face is back, so we need to transform it to opposite face.
  a=[0,              1,    -0.382,    -1][t]*e        #contribution of 5 points x,y,z to triangle tip vertex coordinates
  b=[1.382,          0,     1.382,     1.382][t]*e    #contribution of centre p,q,r to triangle tip vertex coordinates
  c=[-0.528,        -0.382, 1,         0.382][t]*e    #contribution of 5 points x,y,z to coordinates of each triangle base vertex 
  d=[1.901,          1.382, 0,         0][t]*e        #contribution of centre p,q,r to coordinates of each triangle base vertex

  5.times{|i|
  o<<"<path id=\"#{"%9.0f"%(z[i]*a+r*b+(z[i-2]+z[i-3])*c+2*r*d+999)}\"
d=\"M#{(x[i]*a+p*b)} #{(y[i]*a+q*b)}L#{(x[i-2]*c+p*d)} #{(y[i-2]*c+q*d)}L#{(x[i-3]*c+p*d)} #{(y[i-3]*c+q*d)}\"
fill=\"##{m}\"/>"}                                    #write svg code for this triangle 
}

  a=233                                               #a,b =coordinate standard values 
  b=377
  z=[0,a,b,a,0]                                       #z coordinates for one face of stellated dodecahedron 
  y=[a,b,0,-b,-a]                                     #y coordinates
  x=[b,0,-a,0,b]                                      #x coordinates
  w=[-b,0,a,0,-b]                                     #alternate  x coordinates

  f[x,y,z,'F0F']                                      #call f
  f[w,y,z,'0F0']                                      #to plot
  f[y,z,x,'00F']                                      #each
  f[y,z,w,'FF0']                                      #face
  f[z,x,y,'F00']                                      #in
  f[z,w,y,'0FF']                                      #turn

  s=File.open("p.svg","w")                            #sort output in o, plot front triangles last
  s.puts'<svg xmlns="http://www.w3.org/2000/svg" viewBox="-450 -450 900 900">',o.sort,'</svg>'
  s.close                                             #add header and footer, and save as svg
}

t=gets.to_i
n=[]
3.times{n<<gets.to_i}
h[t,n]

산출

작은 별 모양 십이 면체 (다른 다각형의 이미지를 곧 추가 할 것입니다)

1,0,0,0 원위치

여기에 이미지 설명을 입력하십시오

1,30,0,0 30도 회전

여기에 이미지 설명을 입력하십시오

1,0,30,0 오른쪽으로 회전 30 개도 (주 : 완벽한 측면도를 들어, 회전이 될 것 atan(1/golden ratio)= 31.7도 따라서 우리는 여전히 파란색의 작은 은색을 볼 수 있습니다)

여기에 이미지 설명을 입력하십시오

1,0,20,0 20도 오른쪽으로 회전

여기에 이미지 설명을 입력하십시오

1,60,10, -63 아래, 오른쪽 및 위쪽으로 회전 (3 회전 만 가능한 방향 예)

여기에 이미지 설명을 입력하십시오

0,30,0,0 정 십이 면체

여기에 이미지 설명을 입력하십시오

2,0,20,0 큰 십이 면체

여기에 이미지 설명을 입력하십시오

3,45,45,45 큰 별 모양 십이 면체 여기에 이미지 설명을 입력하십시오


3

매스 매 티카, 426424 바이트

Graphics3D[{Red,Yellow,Green,Cyan,Blue,Magenta}~Riffle~(a=Partition)[Polygon/@Uncompress@"1:eJxtkjEKwkAURNeoySYgeAVP4QFsrcTGTiyUBcEith7A2wgKgpVH8/vgs2TYZmAyw9/5k784XDbHVwihnxisU39N9SiEdI8GO/uWHpXBtjFAgJ7HToFl5WabEdJ+anCqDb6dU9RP65NR59EnI0CZDAWYjFmomBmPCn3/hVVwc9s4xYd66wYqFJVvhMz75vWlHIkhG2HBDJ1V3kYps7z7jG6GomIu/QUJKTGkdtlX2pDM8m6pydyzHIOElBhyG6V9cxulzPldaVJ6lpuUkKUTzWcm+0obkrn0f3OT0rMc0jDkD37nlUo="~a~3~a~5,2],Boxed->1<0]

내장을 사용하여 Graphics3D모양을 표시합니다. 그러나 대부분의 바이트는 압축 된 정점 위치에서 차지하며,이 Partition형식은에서 사용할 수있는 형식으로 사용됩니다 Polygon. 드디어:

이 모양은 클릭하고 드래그하여 회전 할 수 있습니다.


세상에, 정 십이 면체를 삭제하려고 했어요! 내가 알 수있는 한 (Mathematica를 모르거나 가지고 있음) 이것은 규칙을 준수하므로 +1입니다.
Level River St

@ steveverrill 크기가 너무 많이 변할 것이라고 생각하지 않지만 처음부터 다시 작성하지 않아도됩니다.
LegionMammal978

귀하의 답변은 유효하며 규칙을 변경하지 않겠습니다. 잘못된 형식 일 것입니다. 그러나 별 모양의 다면체에 대한 0.7 보너스 외에도 4 개의 다면체를 최대한 활용할 수있는 답변에 현상금을 제공했습니다. 답변을 업데이트하기로 결정했다면 알고리즘 적으로 좌표를 생성하여 많은 바이트를 절약 할 수 있다고 생각합니다 (질문의 유용한 정보 섹션 참조)
Level River St

@ steveverrill, 그러나 정점 위치는 quartics의 근본을 포함하며 패턴을 찾을 수 없습니다.
LegionMammal978
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.