红宝石,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三角形。可以以类似的方式通过从数字开始并用p=1
x对其进行异或来获得二进制的sierpinski三角形p<<1
。
我修改了此方法,从开始并p=2
与进行迭代异或p*4
。这给出了一个Sierpinski三角形与零列交替。
现在我们可以右移p并使用来检查最后三个位%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>"