루비, 1168 (932)
어제 밤의 실수를 수정하여 명확하게 한 후 더 많은 골프를칩니다.
이것은 (현재) stdin에서 숫자를 받아 svg
파일을 stdout으로 출력하는 전체 프로그램입니다 . 나는 질문의 모든 요구 사항을 충족시킬 수 있다는 것을 알고 svg를 선택했지만 몇 가지 문제가있었습니다. 특히 SVG는 path
객체의 일부로 원호 만 지원 하며 중심을 기준으로 정의하지 않고 두 끝점으로 정의합니다.
암호
n=gets.to_i
r=64*w=0.75**0.5
m=1<<n-2
z=128*m/w
a=(s="<path style='fill:none;stroke:black;stroke-width:3.464102' transform='translate(%f %f)'
")%[0,r-r*m*8/3]+"d='M18.11943,-2A#{b=r-6*w-32} #{b} 0 0,0 #{-b} 0#{k='A%f %f 0 0 '%([58*w]*2)}0 0,38.71692
M28.58980,1.968882#{l='A%f %f 0 0 '%([70*w]*2)}0 #{c=r+6*w-32} 0A#{c} #{c} 0 0,0 #{-c} 0#{l}0 -9 44.65423'/>"
p=2
m.times{|i|(i*2+1).times{|j|(p>>j)%8%3==2&&a<<s%[128*(j-i),r*3+r*i*4-r*m*8/3]+
"d='M-55,44.65423#{k}0 11.5,25.11473#{l}1 35.41020,1.968882
M-64,51.48786#{l}0 20.5,30.31089#{k}1 36.82830,13.17993
M-82.17170,-2.408529#{l}1 -11.5,25.11473#{k}0 0,38.71692
M-81.52984 8.35435#{k}1 -20.5,30.31089#{l}0 -9,44.65423
M9,44.65423#{k}0 81.52984,8.35435
M0,51.48786#{l}0 91.17169,13.17993'/>"}
p^=p*4}
puts "<svg xmlns='http://www.w3.org/2000/svg' viewBox='#{-z} #{-z} #{e=2*z+1} #{e}' width='#{e}px' height='#{e}px'>"+
"<g transform='rotate(%d)'>#{a}</g>"*3%[0,120,240]+"</svg>"
출력 N = 4
스택 교환에 의해 재조정됩니다. 원본보다 훨씬 나아 보입니다.
설명
처음에 나는 삼각형이 세 개의 다른 색깔의 가닥으로 나뉘는 http://euler.nmt.edu/~jstarret/sierpinski.html 과 같은 것을 고려했는데 , 각 삼각형은 한 모서리에서 다른 모서리로 경로를 형성합니다. 불완전한 원은 불완전한 육각형으로 표시됩니다. 육각형 안에 원을 sqrt(3)/2
그리면 원의 반지름이 측면 길이의 곱 이어야한다는 것을 알 수 있습니다 . 스트랜드는 그림과 같이 재귀 적으로 구축 될 수 있지만 모서리를 둥글게해야하고 곡선 방향을 알기가 어렵 기 때문에 합병증이 추가되어 있으므로이 접근법을 사용하지 않았습니다.
내가 한 것은 다음과 같습니다.
아래 이미지에서 sierpinski 삼각형으로 배열 된 N = 2 단위 (녹색)에 속하는 수평 트위스트와 추가 브리징 트위스트 (파란색)가 있습니다.
파스칼 삼각형의 홀수는 sierpinski 삼각형을 형성한다는 것은 일반적인 지식입니다. 이진수의 sierpinski 삼각형은 숫자로 시작하여 p=1
반복적으로 xoring 하여 유사한 방식으로 얻을 수 있습니다.p<<1
.
에서 시작하여 p=2
반복적으로 xoring 하여이 접근법을 수정했습니다 p*4
. 이것은 0의 열로 번갈아가는 sierpinski 삼각형을 제공합니다.
이제 p를 오른쪽으로 시프트하고을 사용하여 마지막 3 비트를 검사 할 수 있습니다 %8
. 그것들이 있다면 010
N = 2 단위에 속하는 녹색 트위스트를 그려야합니다. 만약 그들이 101
우리 라면 , 푸른 색의 다리를 꼬 아야합니다. 이 두 숫자를 함께 테스트하려면 모듈로를 찾고 %3
이것이 2 인 경우 꼬임을 그려야합니다.
마지막으로 수평 비틀림 외에도 120도 및 240도 회전하여 두 개의 사본을 만들어 대각선 비틀기를 그려 그림을 완성합니다. 남아있는 것은 모서리를 추가하는 것입니다.
주석이 달린 코드
n=gets.to_i
#r=vertical distance between rows
r=64*w=0.75**0.5
#m=number of rows of horizontal twists
m=1<<n-2
#z=half the size of the viewport
z=128*m/w
#s=SVG common to all paths
s="<path style='fill:none;stroke:black;stroke-width:3.464102' transform='translate(%f %f)'
"
#initialize a with SVG to draw top corner loop. Set k and l to the SVG common to all arcs of 58*w and 70*w radius
a=s%[0,r-r*m*8/3]+
"d='M18.11943,-2A#{b=r-6*w-32} #{b} 0 0,0 #{-b} 0#{k='A%f %f 0 0 '%([58*w]*2)}0 0,38.71692
M28.58980,1.968882#{l='A%f %f 0 0 '%([70*w]*2)}0 #{c=r+6*w-32} 0A#{c} #{c} 0 0,0 #{-c} 0#{l}0 -9 44.65423'/>"
#p is the pattern variable, top row of twists has one twist so set to binary 00000010
p=2
#loop vertically and horizontally
m.times{|i|
(i*2+1).times{|j|
#leftshift p. if 3 digits inspected are 010 or 101
(p>>j)%8%3==2&&
#append to a, the common parts of a path...
a<<s%[128*(j-i),r*3+r*i*4-r*m*8/3]+
#...and the SVG for the front strand and left and right parts of the back strand (each strand has 2 borders)
"d='M-55,44.65423#{k}0 11.5,25.11473#{l}1 35.41020,1.968882
M-64,51.48786#{l}0 20.5,30.31089#{k}1 36.82830,13.17993
M-82.17170,-2.408529#{l}1 -11.5,25.11473#{k}0 0,38.71692
M-81.52984 8.35435#{k}1 -20.5,30.31089#{l}0 -9,44.65423
M9,44.65423#{k}0 81.52984,8.35435
M0,51.48786#{l}0 91.17169,13.17993'/>"}
#modify the pattern by xoring with 4 times itself for the next row
p^=p*4}
#output complete SVG of correct size with three copies of the finished pattern rotated through 0,120,240 degrees.
puts "<svg xmlns='http://www.w3.org/2000/svg' viewBox='#{-z} #{-z} #{e=2*z+1} #{e}' width='#{e}px' height='#{e}px'>"+
"<g transform='rotate(%d)'>#{a}</g>"*3%[0,120,240]+"</svg>"