[译] 短小精悍又不可思议的数学艺术挑战赛 - 作品集 2
比赛简介
怎样使用本文中的代码,以及详细比赛规则,请看:https://codebus.cn/yangw/tweetable-mathematical-art
以下是各路大神的优秀作品。
- 作品集 1:https://codebus.cn/yangw/tweetable-mathematical-art-1
- 作品集 2(本文)
- 作品集 3:https://codebus.cn/yangw/tweetable-mathematical-art-3
4. Mandelbrot
by Martin Ender, 122 票。
当然,必须得提交个曼德布洛特集。
代码:
unsigned char RD(int i, int j)
{
float x=0,y=0;int k;for(k=0;k++<256;){float a=x*x-y*y+(i-768.0)/512;y=2*x*y+(j-512.0)/512;x=a;if(x*x+y*y>4)break;}return k>31?256:k*8;
}
unsigned char GR(int i, int j)
{
float x=0,y=0;int k;for(k=0;k++<256;){float a=x*x-y*y+(i-768.0)/512;y=2*x*y+(j-512.0)/512;x=a;if(x*x+y*y>4)break;}return k>63?256:k*4;
}
unsigned char BL(int i, int j)
{
float x=0,y=0;int k;for(k=0;k++<256;){float a=x*x-y*y+(i-768.0)/512;y=2*x*y+(j-512.0)/512;x=a;if(x*x+y*y>4)break;}return k;
}
生成效果:
现在试图改进配色方案。如果我将计算定义为 red_fn 宏并在其他两个函数中使用该宏,以便我有更多的字符用于生成绿色和蓝色的奇幻色彩,这是否算作弊?
用剩下的几个字节想出像样的配色方案真的很难。这是另一个版本:
代码:
unsigned char RD(int i, int j)
{
float x=0,y=0;int k;for(k=0;k++<256;){float a=x*x-y*y+(i-768.0)/512;y=2*x*y+(j-512.0)/512;x=a;if(x*x+y*y>4)break;}return log(k)*47;
}
unsigned char GR(int i, int j)
{
float x=0,y=0;int k;for(k=0;k++<256;){float a=x*x-y*y+(i-768.0)/512;y=2*x*y+(j-512.0)/512;x=a;if(x*x+y*y>4)break;}return log(k)*47;
}
unsigned char BL(int i, int j)
{
float x=0,y=0;int k;for(k=0;k++<256;){float a=x*x-y*y+(i-768.0)/512;y=2*x*y+(j-512.0)/512;x=a;if(x*x+y*y>4)break;}return 128-log(k)*23;
}
生成效果:
根据 githubphagocyte 的建议和 Todd Lehman 的改进,我们可以很容易地选择局部放大的部分。例如:
代码:
unsigned char RD(int i, int j)
{
float x=0,y=0,k=0,X,Y;while(k++<256e2&&(X=x*x)+(Y=y*y)<4)y=2*x*y+(j-89500)/102400.,x=X-Y+(i-14680)/102400.;return log(k)/10.15*256;
}
unsigned char GR(int i, int j)
{
float x=0,y=0,k=0,X,Y;while(k++<256e2&&(X=x*x)+(Y=y*y)<4)y=2*x*y+(j-89500)/102400.,x=X-Y+(i-14680)/102400.;return log(k)/10.15*256;
}
unsigned char BL(int i, int j)
{
float x=0,y=0,k=0,X,Y;while(k++<256e2&&(X=x*x)+(Y=y*y)<4)y=2*x*y+(j-89500)/102400.,x=X-Y+(i-14680)/102400.;return 128-k/200;
}
生成效果:
5. Mandelbrot 3 x 133 chars
by Manuel Kasten,120 票。
我脑海中浮现的第一件事是“曼德布洛特集”!
我知道已经有人提交了曼德布洛特集。在确认我自己能够将其保持在 140 个字符以下后,我将该解决方案中的技巧和优化应用到我的解决方案中(感谢 Martin 和 Todd)。省下来的字符可以选择一个有趣的位置和缩放,以及一个漂亮的颜色主题。
代码:
unsigned char RD(int i, int j){
double a=0,b=0,c,d,n=0;
while((c=a*a)+(d=b*b)<4&&n++<880)
{b=2*a*b+j*8e-9-.645411;a=c-d+i*8e-9+.356888;}
return 255*pow((n-80)/800,3.);
}
unsigned char GR(int i, int j){
double a=0,b=0,c,d,n=0;
while((c=a*a)+(d=b*b)<4&&n++<880)
{b=2*a*b+j*8e-9-.645411;a=c-d+i*8e-9+.356888;}
return 255*pow((n-80)/800,.7);
}
unsigned char BL(int i, int j){
double a=0,b=0,c,d,n=0;
while((c=a*a)+(d=b*b)<4&&n++<880)
{b=2*a*b+j*8e-9-.645411;a=c-d+i*8e-9+.356888;}
return 255*pow((n-80)/800,.5);
}
实现效果:
一共只有 132 字符的版本:
我试图将所有 3 个颜色通道的代码缩减到 140 字符,可惜边缘附近有一点色彩噪点,位置没有第一个那幺有趣。但是:只有 132 个字符。
代码:
unsigned char RD(int i, int j){
double a=0,b=0,d,n=0;
for(;a*a+(d=b*b)<4&&n++<8192;b=2*a*b+j/5e4+.06,a=a*a-d+i/5e4+.34);
return n/4;
}
unsigned char GR(int i, int j){
return 2*RD(i,j);
}
unsigned char BL(int i, int j){
return 4*RD(i,j);
}
实现效果:
6. Julia sets
by teh internets is made of catz,110 票。
如果有曼德布洛特集,也应该有朱莉娅集。
你可以花几小时来调整这些参数和功能,这只是一个我简单调整的看起来还不错的一组。
灵感来自 Martin 提交的作品。
代码:
unsigned char RD(int i, int j){
#define D(x) (x-DIM/2.)/(DIM/2.)
float x=D(i),y=D(j),X,Y,n=0;while(n++<200&&(X=x*x)+(Y=y*y)<4){x=X-Y+.36237;y=2*x*y+.32;}unsigned short N = log(n)*256;
N &= DM1;
return N * 255 / 1023;
}
unsigned char GR(int i, int j){
float x=D(i),y=D(j),X,Y,n=0;while(n++<200&&(x*x+y*y)<4){X=x;Y=y;x=X*X-Y*Y+-.7;y=2*X*Y+.27015;}unsigned short N = log(n)*128;
N &= DM1;
return N * 255 / 1023;
}
unsigned char BL(int i, int j){
float x=D(i),y=D(j),X,Y,n=0;while(n++<600&&(x*x+y*y)<4){X=x;Y=y;x=X*X-Y*Y+.36237;y=2*X*Y+.32;}unsigned short N = log(n)*128;
N &= DM1;
return N * 255 / 1023;
}
实现效果:
想要生成一些随机图案吗?
Sparr 的评论让我开始尝试随机化这些朱莉娅集的参数。我首先尝试使用 time(0) 的结果进行位级的操作,但 C 不直接支持这么操作十六进制浮点数,所以这是一个死胡同(我知识有限)。我本可以多写几个字符通过强制转换来实现它,但这不适合 140 字节的比赛要求。
我剩下的空间不多,所以不得不放弃红色通道的代码来放置我的宏,以及一个更传统的随机数发生器(定时种子和真正的 rand(),吼吼!)
(作为中间步骤,作者未给出对应的代码)
哎呀,少了点什幺。显然,这些参数必须是静态的,否则你会得到一些奇怪的结果(但是有趣。如果我发现了有趣的东西,稍后再琢磨)。
所以目前,只有绿色和蓝色通道:
现在,我们添加一个简单的红色图案来填补空白。可惜我不是图形进程员,不是很有想象力…… :-)
最后,是带有随机参数的新代码:
unsigned char RD(int i, int j){
static int n=1;if(n){--n;srand(time(0));}
#define R rand()/16384.-1
#define S static float r=R,k=R;float
unsigned short N = _cb(i^j);
N &= DM1;
return N * 255 / 1023;
}
unsigned char GR(int i, int j){
#define D(x) (x-DIM/2.)/(DIM/2.),
S x=D(i)y=D(j)X,Y;int n=0;while(n++<200&&(X=x)*x+(Y=y)*y<4){x=X*X-Y*Y+r;y=2*X*Y+k;}unsigned short N = log(n)*512;
N &= DM1;
return N * 255 / 1023;
}
unsigned char BL(int i, int j){
S x=D(i)y=D(j)X,Y;int n=0;while(n++<200&&(X=x)*x+(Y=y)*y<4){x=X*X-Y*Y+r;y=2*X*Y+k;}unsigned short N = log(n)*512;
N &= DM1;
return N * 255 / 1023;
}
实现效果(注意,因为是随机生成的图案,每次执行的效果都不同):
还剩下一些字符空间没用完……
添加评论
取消回复