MATLAB:735バイト-200ボーナス= 535
私のプログラムはn = 2のケースを処理し、リアルタイムのアニメーションを描画します。ゴルフバージョンと非ゴルフバージョンにはいくつかの違いがあります。
改変されていないバージョンにsavegif = 1
は、コードで設定することにより、アニメーションをファイル「g.gif」に保存するオプションのみがあります。いくつかの理由で迷惑になる可能性があるため、デフォルトではオフになっています。
- 不要なファイルの作成
- 遅延の可能性
- 複数のモニターがあり、プロットウィンドウが右側にない場合は、エラーが生成されます...
ゴルフバージョンでは、ボーナスのサイズを超えて約100バイトかかったため、gifの保存を中止する必要がありました。
改変されていないバージョンは、トレーサーの頂点に円を描きます。また、より多くのフレームを生成し、より速く移動します(ただし、これはゴルフバージョンでは数値を変更することで調整できます)。
サンプル:
f(11,5,90,2,99,0)
プログラム終了後
epic(1.3,4,2,6,6,1)
gif出力付き
未ゴルフコード
%epicyclogon animation outputs to 'g.gif' if savegif=1 as well as animating in real time
function[] = epic(r,r1,r2,n1,n2,dispPoly)
savegif = 0; %set to 1 to write .gif
cs = @(a) [cos(a);sin(a)];
vert = @(r, n, v) r * cs(2*pi*v/n);
polyPt = @(l, s, n, r) vert(r, n, floor(l/s)) + mod(l/s,1)*(vert(r, n, floor(l/s)+1) - vert(r, n, floor(l/s)));
polyPt2 = @(i, f, n, r) vert(r, n, i) + f*(vert(r, n, i+1) - vert(r, n, i));
rotm = @(a) [cos(a) -sin(a);sin(a) cos(a)];
arrpluspt = @(a, p) a + kron(p, ones(1,length(a)));
arg = @(p) atan2(p(2), p(1));
E = 1e-9;
dispPoly = dispPoly / dispPoly;
sgn = sign(-r);
r = abs(r);
s1 = 2*r1*sin(pi/n1);
s2 = 2*r2*sin(pi/n2);
%d1 = (r1*r1 - s1*s1*.25)^.5;
d2 = (r2*r2 - s2*s2*.25)^.5;
plotmax = r1+2*r2;
astep = .05; %determines amount of frames per rotation
delay = .01; % time per frame
l = 0;
lRem = 0;
lr = 0;
P1 = vert(r1, n1, 1:n1+1) * dispPoly;
trace = [];
first = 1;
while 1
if lr %exists while rotating about a corner of the stationary
rotA = 2*pi/n1;
else
rotA = 2*pi/n2;
end
rotPt = polyPt(l, s1, n1, r1);
lb = l + lRem;
side1 = floor(l / s1 - E);
side1up = side1 + lr;
p2cen = polyPt2(side1, lb/s1 -side1 - .5 * s2/s1, n1, r1) + d2 * cs(2*pi*(side1+.5)/n1);
if first
p2cen0 = p2cen;
r = r + arg(p2cen0)/(2*pi);
end
for a = 0:astep:rotA
P2 = vert(r2, n2, 0:n2);
P2 = rotm( pi +pi/n1 -pi/n2 +2*pi*side1/n1) * P2;
P2 = arrpluspt(P2, p2cen);
P2 = arrpluspt(P2, -rotPt);
P2 = rotm(a) * P2;
P2 = arrpluspt(P2, rotPt);
trV = mod(floor(l/s2 + E) + lr, n2) + 1;
cen = rotm(a) * (p2cen - rotPt) + rotPt;
trace = [trace,P2(:,trV)];
plot(P1(1,:), sgn*P1(2,:), P2(1,:)*dispPoly, sgn*P2(2,:)*dispPoly, trace(1,:),sgn*trace(2,:),P2(1,trV), sgn*P2(2,trV),'o');
%plot(P1(1,:), P1(2,:), P2(1,:), P2(2,:), trace(1,:),trace(2,:),...
%[0,p2cen0(1)],[0,p2cen0(2)],[0,cen(1)],[0,cen(2)], P2(1,trV), P2(2,trV),'o');
axis([-plotmax,plotmax,-plotmax,plotmax]);
axis square
figure(1);
if savegif
drawnow
frame = getframe(1); % plot window must be on same monitor!
img = frame2im(frame);
[img1,img2] = rgb2ind(img,256);
end
if first
if savegif
imwrite(img1,img2,'g','gif','DelayTime',2*delay); %control animation speed(but not really)
end
first = 0;
else
if savegif
imwrite(img1,img2,'g','gif','WriteMode','append','DelayTime', 2*delay);
end
end
pause(.01);
adf = mod(arg(cen) - r*2*pi, 2*pi);
if adf < astep & l/(n1*s1) + .5 > r
return
end
end
%cleanup for next iteration
jump = lRem + ~lr * s2;
lnex = l + jump;
if floor(lnex / s1 - E) > side1up
lnex = s1*(side1up+1);
lRem = jump - (lnex - l);
lr = 1;
else
lRem = 0;
lr = 0;
end
l = lnex;
end
ゴルフコード
function[]=f(r,h,H,n,N,d)
P=pi;T=2*P;F=@floor;C=@(a)[cos(a);sin(a)];g=@(i,f,n,r)r*C(T*i/n)*(1-f)+f*r*C(T*(i+1)/n);R=@(a)[C(a),C(a+P/2)];W=@(a,p)[a(1,:)+p(1);a(2,:)+p(2)];b=@(p)atan2(p(2),p(1));E=1e-9;d=d/d;S=1-2*(r>0);r=-r*S;x=2*h*sin(P/n);X=2*H*sin(P/N);M=h+2*H;l=0;z=0;L=0;A=h*C(T*(0:n)/n)*d;t=[];while 1
v=l/x;D=F(v-E);q=g(D,v-D,n,h);Z=D+L;c=g(D,v+z/x-D-.5*X/x,n,h)+H*cos(P/N)*C(T*D/n+P/n);r=r+~(l+L)*b(c)/T;for a=0:.1:T/(L*n+~L*N)
O=@(p)W(R(a)*W(p,-q),q);B=O(W(R(P+P/n-P/N+T*D/n)*H*C(T*(0:N)/N),c));t=[t,B(:,mod(F(l/X+E)+L,N)+1)];plot(A(1,:),S*A(2,:),d*B(1,:),d*S*B(2,:),t(1,:),t(2,:)*S)
axis([-M,M,-M,M],'square');pause(.1);if.1>mod(b(O(c))-r*T,T)&v/n+.5>r
return;end;end;j=z+~L*X;J=l+j;L=F(J/x-E)>Z;l=L*x*(Z+1)+~L*J;z=L*(J-l);end
手順:
関数を同じ名前、つまりepic.m
またはでファイルに保存しますf.m
。Matlabコンソールから関数を呼び出して実行します。
使用法:epic(r, r1, r2, n1, n2, dispPoly)
where dispPoly
は、ポリゴンを描画するかどうかを決定するブール変数(falseの場合はゼロ、trueの場合はゼロ以外の数値)です。
編集:アニメーション画像に50のボーナスを追加しました。