慢羊羊的空间

无为,无我,无欲,居下,清虚,自然

[译] 短小精悍又不可思议的数学艺术挑战赛 - 作品集 2

比赛简介

怎样使用本文中的代码,以及详细比赛规则,请看:https://codebus.cn/yangw/tweetable-mathematical-art 

以下是各路大神的优秀作品。

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;
}

实现效果(注意,因为是随机生成的图案,每次执行的效果都不同):

还剩下一些字符空间没用完……

添加评论