Tweetable Mathematical Art: Generating Images with Compact C++ Functions
The Tweetable Mathematical Art contest challenges participants to craft three ultra‑compact C++ functions—each under 140 characters—to compute red, green, and blue values for every pixel of a 1024×1024 image, yielding striking patterns ranging from trigonometric color wheels to Mandelbrot fractals and diffusion‑limited aggregations.
Hi everyone. In computer graphics a color is usually described by three integers R, G, B in the range 0‑255. Every pixel on the screen can therefore be represented by an RGB triple.
The question posed by the "Tweetable Mathematical Art" competition is: if a program automatically fills each pixel, what picture will it produce?
The competition, hosted on StackExchange, asks participants to write three C++ functions RD , GR and BL (for red, green and blue). Each function must be no longer than 140 characters, accept two integer parameters i and j (0 ≤ i, j ≤ 1023), and return an integer 0‑255 representing the colour component at pixel (i, j). The functions are then plugged into a driver program that generates a 1024×1024 PPM image.
Driver program (unchanged apart from minor tweaks):
#include <iostream>
#include <cmath>
#include <cstdlib>
#define DIM 1024
#define DM1 (DIM-1)
#define _sq(x) ((x)*(x))
#define _cb(x) abs((x)*(x)*(x))
#define _cr(x) (unsigned char)(pow((x),1.0/3.0))
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\n255\n", DIM, DIM);
for(int j=0;j
Below are several striking artworks created for the contest, together with the source code that produced them.
Martin Büttner’s first piece:
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);
}
A second, higher‑ranking work by the same author uses recursion and static storage:
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];
}
Manuel Kasten contributed a Mandelbrot‑set zoom, generated with the following compact functions:
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);
}
Another style relies on static variables to drive the colour evolution without using the coordinates at all:
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 posted a diffusion‑limited‑aggregation based generator that squeezes three functions into the 140‑character limit by sharing macros:
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()%2000?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
2){B=f-1;}else{++e%=4;d=e; if(!c[e]){B=0;M=1;}}}}}
return m[i][j];
}
Eric Tressler demonstrated a logistic‑map based Feigenbaum bifurcation picture, again using macro tricks to stay within the size limit:
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/2){e=a;o=(E*x);c[e][o]+=0.01;}}}}}
R C(c[j][i])*i/D;
}
These examples show how a few dozen characters of C++ can produce surprisingly rich visual patterns, ranging from trigonometric colour maps to classic fractals. Feel free to copy the snippets and experiment with your own ideas.Java Tech Enthusiast
Sharing computer programming language knowledge, focusing on Java fundamentals, data structures, related tools, Spring Cloud, IntelliJ IDEA... Book giveaways, red‑packet rewards and other perks await!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.