當前位置: 華文問答 > 數位

有沒有一段程式碼,讓你為人類的智慧擊節叫好?

2020-02-16數位

當然是這個啦!

用三段 140 字元以內的程式碼生成一張 1024×1024 的圖片

原文 by Matrix67

Kyle McCormick 在 StackExchange 上發起了一個叫做 Tweetable Mathematical Art 的比賽,參賽者需要用三條推這麽長的程式碼來生成一張圖片。具體地說,參賽者需要用 C++ 語言編寫 RD 、 GR 、 BL 三個函式,每個函式都不能超過 140 個字元。每個函式都會接到 i 和 j 兩個整型參數(0 ≤ i, j ≤ 1023),然後需要返回一個 0 到 255 之間的整數,表示位於 (i, j) 的像素點的顏色值。舉個例子,如果 RD(0, 0) 和 GR(0, 0) 返回的都是 0 ,但 BL(0, 0) 返回的是 255 ,那麽影像的最左上角那個像素就是藍色。參賽者編寫的程式碼會被插進下面這段程式當中(我做了一些細微的改動),最終會生成一個大小為 1024×1024 的圖片。

// NOTE: compile with g++ filename.cpp -std=c++11 #include <iostream> #include <cmath> #include <cstdlib> #define DIM 1024 #define DM1 (DIM-1) #define _sq(x) ((x)*(x)) // square #define _cb(x) abs((x)*(x)*(x)) // absolute value of cube #define _cr(x) (unsigned char)(pow((x),1.0/3.0)) // cube root unsigned char GR ( int , int ); unsigned char BL ( int , int ); unsigned char RD ( int i , int j ){ // YOUR CODE HERE } unsigned char GR ( int i , int j ){ // YOUR CODE HERE } unsigned char BL ( int i , int j ){ // YOUR CODE HERE } void pixel_write ( int , int ); FILE * fp ; int main (){ fp = fopen ( "MathPic.ppm" , "wb" ); fprintf ( fp , "P6 \n %d %d \n 255 \n " , DIM , DIM ); for ( int j = 0 ; j < DIM ; j ++ ) for ( int i = 0 ; i < DIM ; i ++ ) pixel_write ( i , j ); fclose ( fp ); return 0 ; } void pixel_write ( int i , int j ){ static unsigned char color [ 3 ]; color [ 0 ] = RD ( i , j ) & 255 ; color [ 1 ] = GR ( i , j ) & 255 ; color [ 2 ] = BL ( i , j ) & 255 ; fwrite ( color , 1 , 3 , fp ); }


我選了一些自己比較喜歡的作品,放在下面和大家分享。

首先是一個來自 Martin Büttner 的作品:

它的程式碼如下:

unsigned char RD ( int i , int j ){ return ( char )( _sq ( cos ( atan2 ( j - 512 , i - 512 ) / 2 )) * 255 ); } unsigned char GR ( int i , int j ){ return ( char )( _sq ( cos ( atan2 ( j - 512 , i - 512 ) / 2 - 2 * acos ( - 1 ) / 3 )) * 255 ); } unsigned char BL ( int i , int j ){ return ( char )( _sq ( cos ( atan2 ( j - 512 , i - 512 ) / 2 + 2 * acos ( - 1 ) / 3 )) * 255 ); }


同樣是來自 Martin Büttner 的作品:
這是目前暫時排名第一的作品。它的程式碼如下:

unsigned char RD ( int i , int j ){ #define r(n)(rand()%n) static char c [ 1024 ][ 1024 ]; return ! c [ i ][ j ] ? c [ i ][ j ] =! r ( 999 ) ? r ( 256 ) : RD (( i + r ( 2 )) % 1024 ,( j + r ( 2 )) % 1024 ) : c [ i ][ j ]; } unsigned char GR ( int i , int j ){ static char c [ 1024 ][ 1024 ]; return ! c [ i ][ j ] ? c [ i ][ j ] =! r ( 999 ) ? r ( 256 ) : GR (( i + r ( 2 )) % 1024 ,( j + r ( 2 )) % 1024 ) : c [ i ][ j ]; } unsigned char BL ( int i , int j ){ static char c [ 1024 ][ 1024 ]; return ! c [ i ][ j ] ? c [ i ][ j ] =! r ( 999 ) ? r ( 256 ) : BL (( i + r ( 2 )) % 1024 ,( j + r ( 2 )) % 1024 ) : c [ i ][ j ]; }


下面這張圖片仍然出自 Martin Büttner 之手:
難以想象, Mandelbrot 碎形圖形居然可以只用這麽一點程式碼畫出:

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


Manuel Kasten 也制作了一個 Mandelbrot 集的圖片,與剛才不同的是,該圖描繪的是 Mandelbrot 集在某處局部放大後的結果:
它的程式碼如下:

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


這是 Manuel Kasten 的另一作品:
生成這張圖片的程式碼很有意思:函式依靠 static 變量來控制繪畫的行程,完全沒有用到 i 和 j 這兩個參數!

unsigned char RD ( int i , int j ){ static double k ; k += rand () / 1. / RAND_MAX ; int l = k ; l %= 512 ; return l > 255 ? 511 - l : l ; } unsigned char GR ( int i , int j ){ static double k ; k += rand () / 1. / RAND_MAX ; int l = k ; l %= 512 ; return l > 255 ? 511 - l : l ; } unsigned char BL ( int i , int j ){ static double k ; k += rand () / 1. / RAND_MAX ; int l = k ; l %= 512 ; return l > 255 ? 511 - l : l ; }


這是來自 githubphagocyte 的作品:
它的程式碼如下:

unsigned char RD ( int i , int j ){ float s = 3. / ( j + 99 ); float y = ( j + sin (( i * i + _sq ( j - 700 ) * 5 ) / 100. / DIM ) * 35 ) * s ; return ( int (( i + DIM ) * s + y ) % 2 + int (( DIM * 2 - i ) * s + y ) % 2 ) * 127 ; } unsigned char GR ( int i , int j ){ float s = 3. / ( j + 99 ); float y = ( j + sin (( i * i + _sq ( j - 700 ) * 5 ) / 100. / DIM ) * 35 ) * s ; return ( int ( 5 * (( i + DIM ) * s + y )) % 2 + int ( 5 * (( DIM * 2 - i ) * s + y )) % 2 ) * 127 ; } unsigned char BL ( int i , int j ){ float s = 3. / ( j + 99 ); float y = ( j + sin (( i * i + _sq ( j - 700 ) * 5 ) / 100. / DIM ) * 35 ) * s ; return ( int ( 29 * (( i + DIM ) * s + y )) % 2 + int ( 29 * (( DIM * 2 - i ) * s + y )) % 2 ) * 127 ; }


這是來自 githubphagocyte 的另一個作品:
這是一張使用 diffusion-limited aggregation 模型得到的圖片,程式執行起來要耗費不少時間。程式碼很有意思:巧妙地利用宏定義,打破了函式與函式之間的界限,三段程式碼的字數限制便能合在一起使用了。

unsigned char RD ( int i , int j ){ #define D DIM #define M m[(x+D+(d==0)-(d==2))%D][(y+D+(d==1)-(d==3))%D] #define R rand()%D #define B m[x][y] return ( i + j ) ? 256 - ( BL ( i , j )) / 2 : 0 ; } unsigned char GR ( int i , int j ){ #define A static int m[D][D],e,x,y,d,c[4],f,n;if(i+j<1){for(d=D*D;d;d--){m[d%D][d/D]=d%6?0:rand() 00?1:255;}for(n=1 return RD ( i , j ); } unsigned char BL ( int i , int j ){ A ; n ; n ++ ){ x = R ; y = R ; if ( B == 1 ){ f = 1 ; for ( d = 0 ; d < 4 ; d ++ ){ c [ d ] = M ; f = f < c [ d ] ? c [ d ] : f ;} if ( f > 2 ){ B = f - 1 ;} else { ++ e %= 4 ; d = e ; if ( ! c [ e ]){ B = 0 ; M = 1 ;}}}}} return m [ i ][ j ]; }


最後這張圖來自 Eric Tressler:
這是由 logistic 對映得到的 Feigenbaum 分岔圖。和剛才一樣,對應的程式碼也巧妙地利用了宏定義來節省字元:

unsigned char RD ( int i , int j ){ #define A float a=0,b,k,r,x #define B int e,o #define C(x) x>255?255:x #define R return #define D DIM R BL ( i , j ) * ( D - i ) / D ; } unsigned char GR ( int i , int j ){ #define E DM1 #define F static float #define G for( #define H r=a*1.6/D+2.4;x=1.0001*b/D R BL ( i , j ) * ( D - j / 2 ) / D ; } unsigned char BL ( int i , int j ){ F c [ D ][ D ]; if ( i + j < 1 ){ A ; B ; G ; a < D ; a += 0.1 ){ G b = 0 ; b < D ; b ++ ){ H ; G k = 0 ; k < D ; k ++ ){ x = r * x * ( 1 - x ); if ( k > D / 2 ){ e = a ; o = ( E * x ); c [ e ][ o ] += 0.01 ;}}}}} R C ( c [ j ][ i ]) * i / D ; }