Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

Integer math can generate amazing patterns when laid out over a grid. Even the most basic functions can yield stunningly elaborate designs!

Your challenge

Write 3 Tweetable (meaning 140 characters or less) function bodies for the red, green, and blue values for a 1024x1024 image.

The input to the functions will be two integers i (column number for the given pixel) and j (row number for the given pixel) and the output will be an unsigned short between 0 and 1023, inclusive, which represents the amount of the given color present in the pixel (i,j).

For example, the following three functions produce the picture below:

/* RED */
    return (unsigned short)sqrt((double)(_sq(i-DIM/2)*_sq(j-DIM/2))*2.0);
/* GREEN */
    return (unsigned short)sqrt((double)(
        (_sq(i-DIM/2)|_sq(j-DIM/2))*
        (_sq(i-DIM/2)&_sq(j-DIM/2))
    )); 
/* BLUE */
    return (unsigned short)sqrt((double)(_sq(i-DIM/2)&_sq(j-DIM/2))*2.0);

Pattern-1

/* RED */
    return i&&j?(i%j)&(j%i):0;
/* GREEN */
    return i&&j?(i%j)+(j%i):0;
/* BLUE */
    return i&&j?(i%j)|(j%i):0;

Pattern-2

The Rules

  • Given this C++ code, substitute in your functions. I have provided a few macros and have included the library, and you may include complex.h. You may use any functions from these libraries and/or my macros. Please do not use any external resources beyond this.
  • If that version isn't working for you, make sure you're compiling with:

    g++ filename.cpp -std=c++11
    

    If that doesn't work, please use the alternate version using unsigned chars instead of unsigned shorts.

Michaelangelo has provided a cleaned up 24-bit or 48-bit color output version.

  • You may implement your own version in another language, but it must behave in the same way as the provided C++ version, and only functions from C++'s built-ins, the library, or the provided macros may be used to make it fair.
  • Post only your three function bodies - please don't include my code in your post
  • Please include either a smaller version or an embedded copy of your image. They are made into a ppm format and may need to be converted to another for proper viewing on stackexchange.
  • Function bodies (not including signature) must be 140 characters or less.
  • This is a popularity contest - most votes wins
share|improve this question
2  
Added C++ tag because the nature of the rules excludes other languages. We generally prefer language-agnostic challenges unless they have a good reason to require a specific set. –  algorithmshark Aug 2 at 4:48
4  
To the close voters calling this too broad, please try writing an answer to this first. It's surprisingly restrictive... –  githubphagocyte Aug 3 at 22:24
8  
This is my favorite thing I've seen on here in, like, ever! –  David Conrad Aug 4 at 16:25
4  
I love that this question feels like an old-school demo scene. –  mskfisher Aug 5 at 13:31
14  
This type of question encourages participation in code golf. I'm generally disinclined to answer a straight golf question as I'm not confident of doing well. With this type of question the byte limit makes me try a simple answer, learn golfing techniques along the way, and then use them to make more complex answers. This is like a stepping stone into answering straight golf questions. I think it could be key in bringing more people in. –  githubphagocyte Aug 7 at 23:43

56 Answers 56

Table cloths

Flat

I started out putting a plaid/gingham pattern into perspective like a boundless table cloth:

unsigned char RD(int i,int j){
    float s=3./(j+99);
    return (int((i+DIM)*s+j*s)%2+int((DIM*2-i)*s+j*s)%2)*127;
}
unsigned char GR(int i,int j){
    float s=3./(j+99);
    return (int((i+DIM)*s+j*s)%2+int((DIM*2-i)*s+j*s)%2)*127;
}
unsigned char BL(int i,int j){
    float s=3./(j+99);
    return (int((i+DIM)*s+j*s)%2+int((DIM*2-i)*s+j*s)%2)*127;
}

flat table cloth

Ripple

Then I introduced a ripple (not strictly correct perspective, but still in 140 characters):

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((i+DIM)*s+y)%2+int((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((i+DIM)*s+y)%2+int((DIM*2-i)*s+y)%2)*127;
}

rippled table cloth

Colour

Then I made some of the colours more fine grained to give detail on a wider range of scales, and to make the picture more colourful...

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

coloured table cloth

In motion

Reducing the code just slightly more allows for defining a wave phase P with 2 decimal places, which is just enough for frames close enough for smooth animation. I've reduced the amplitude at this stage to avoid inducing sea sickness, and shifted the whole image up a further 151 pixels (at the cost of 1 extra character) to push the aliasing off the top of the image. Animated aliasing is mesmerising.

unsigned char RD(int i,int j){
#define P 6.03
float s=3./(j+250),y=(j+sin((i*i+_sq(j-700)*5)/100./DIM+P)*15)*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+250);
float y=(j+sin((i*i+_sq(j-700)*5)/100./DIM+P)*15)*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+250);
float y=(j+sin((i*i+_sq(j-700)*5)/100./DIM+P)*15)*s;
return (int(29*((i+DIM)*s+y))%2+int(29*((DIM*2-i)*s+y))%2)*127;}

animated table cloth

share|improve this answer
9  
This is legendary. (Y) Keep it up. :P –  Mohammad Areeb Siddiqui Aug 8 at 16:15
1  
Thank you @MohammadAreebSiddiqui :) –  githubphagocyte Aug 8 at 22:33
    
But how exactly motion is implemented? In original framework there's no frame changing logic, is there? –  esteewhy Aug 12 at 15:34
1  
@esteewhy only still images can be produced. The GIF shows a sequence of still frames, each of which was produced by changing the value after #define P. It required golfing down to allow the additional characters for #define P 6.03. –  githubphagocyte Aug 12 at 16:03
    
Great! Managed to implement this interactively in my improvised playground (+few other algos from here), DEMO: jsfiddle.net/esteewhy/czgy40kx/embedded/result, SOURCE: jsfiddle.net/esteewhy/czgy40kx (Sadly, comments are off, so posting here) –  esteewhy Aug 14 at 13:26

Random painter

enter image description here

char red_fn(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):red_fn((i+r(2))%1024,(j+r(2))%1024):c[i][j];
}
char green_fn(int i,int j){
    static char c[1024][1024];return!c[i][j]?c[i][j]=!r(999)?r(256):green_fn((i+r(2))%1024,(j+r(2))%1024):c[i][j];
}
char blue_fn(int i,int j){
    static char c[1024][1024];return!c[i][j]?c[i][j]=!r(999)?r(256):blue_fn((i+r(2))%1024,(j+r(2))%1024):c[i][j];
}

Here is a randomness-based entry. For about 0.1% of the pixels it chooses a random colour, for the others it uses the same colour as a random adjacent pixel. Note that each colour does this independently, so this is actually just an overlay of a random green, blue and red picture. To get different results on different runs, you'll need to add srand(time(NULL)) to the main function.

Now for some variations.

By skipping pixels we can make it a bit more blurry.

enter image description here

And then we can slowly change the colours, where the overflows result in abrupt changes which make this look even more like brush strokes

enter image description here

Things I need to figure out:

  • For some reason I can't put srand within those functions without getting a segfault.
  • If I could make the random walks the same across all three colours it might look a bit more orderly.

You can also make the random walk isotropic, like

static char c[1024][1024];return!c[i][j]?c[i][j]=r(999)?red_fn((i+r(5)+1022)%1024,(j+r(5)+1022)%1024):r(256):c[i][j];

to give you

enter image description here

More random paintings

I've played around with this a bit more and created some other random paintings. Not all of these are possible within the limitations of this challenge, so I don't want to include them here. But you can see them in this imgur gallery along with some descriptions of how I produced them.

I'm tempted to develop all these possibilities into a framework and put it on GitHub. (Not that stuff like this doesn't already exist, but it's fun anyway!)

share|improve this answer
9  
I love these. I hadn't realised it would be possible to take into account adjacent pixels without having access to the pixel data - smooth work! –  githubphagocyte Aug 2 at 17:11
1  
Reminds me very much of this old contest where the rules were to put a pixel of every color in the image. –  teh internets is made of catz Aug 3 at 10:20
    
@tehinternetsismadeofcatz yes there were some great random entries in images with all colors. Good luck fitting those into 140 bytes though... –  githubphagocyte Aug 3 at 15:08
2  
Wow! These pictures are absolutely beautiful! –  raptortech97 Aug 6 at 20:03
1  
I see Reptar: last image in the post (the isotropic one), top-right quadrant. –  Tim Pederick Aug 11 at 12:39

Some swirly pointy things

Yes, I knew exactly what to name it.

Some swirly pointy things

unsigned short RD(int i,int j){
    return(sqrt(_sq(73.-i)+_sq(609-j))+1)/(sqrt(abs(sin((sqrt(_sq(860.-i)+_sq(162-j)))/115.0)))+1)/200;
}
unsigned short GR(int i,int j){
    return(sqrt(_sq(160.-i)+_sq(60-j))+1)/(sqrt(abs(sin((sqrt(_sq(86.-i)+_sq(860-j)))/115.0)))+1)/200;
}
unsigned short BL(int i,int j){
    return(sqrt(_sq(844.-i)+_sq(200-j))+1)/(sqrt(abs(sin((sqrt(_sq(250.-i)+_sq(20-j)))/115.0)))+1)/200;
}

EDIT: No longer uses pow. EDIT 2: @PhiNotPi pointed out that I don't need to use abs as much.

You can change the reference points pretty easily to get a different picture:

Some more swirly pointy things

unsigned short RD(int i,int j){
    return(sqrt(_sq(148.-i)+_sq(1000-j))+1)/(sqrt(abs(sin((sqrt(_sq(500.-i)+_sq(400-j)))/115.0)))+1)/200;
}
unsigned short GR(int i,int j){
    return(sqrt(_sq(610.-i)+_sq(60-j))+1)/(sqrt(abs(sin((sqrt(_sq(864.-i)+_sq(860-j)))/115.0)))+1)/200;
}
unsigned short BL(int i,int j){
    return(sqrt(_sq(180.-i)+_sq(100-j))+1)/(sqrt(abs(sin((sqrt(_sq(503.-i)+_sq(103-j)))/115.0)))+1)/200;
}

@EricTressler pointed out that my pictures have Batman in them.

Batman

share|improve this answer
1  
@JayKominek I wouldn't know, I wasn't around back then d: –  cjfaure Aug 4 at 21:53
2  
@JayKominek I found it. web.archive.org/web/19990221092445/http://www.blorf.com/… –  cjfaure Aug 5 at 8:51
1  
@cjfaure oh wow! thank you! it looks like the final version of the description is at: web.archive.org/web/20031205062033/http://www.blorf.com/~mrad/… and the code was moved to sourceforge. updated last year even! sourceforge.net/projects/libswirlies –  Jay Kominek Aug 5 at 21:00
1  
One of my favorites! –  Calvin's Hobbies Aug 6 at 0:23
1  
This one is pretty -- but I can't reproduce it at all! Closest I can get is when the PPM is generated improperly (LSB instead of MSB) and even then it just looks like a variety of alpha-blended circles of different color. –  DreamWarrior Aug 6 at 19:43

Of course, there has to be a Mandelbrot submission.

enter image description here

char red_fn(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;
}
char green_fn(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;
}
char blue_fn(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;
}

Trying to improve the colour scheme now. Is it cheating if I define the computation as a macro is red_fn and use that macro in the other two so I have more characters for fancy colour selection in green and blue?

Edit: It's really hard to come up with decent colour schemes with these few remaining bytes. Here is one other version:

/* RED   */ return log(k)*47;
/* GREEN */ return log(k)*47;
/* BLUE  */ return 128-log(k)*23;

enter image description here

And as per githubphagocyte's suggestion and with Todd Lehman's improvements, we can easily pick smaller sections:

E.g.

char red_fn(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;
}
char green_fn(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;
}
char blue_fn(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;
}

gives

enter image description here

share|improve this answer
10  
@tomsmeding I have to confess, this is the first time I ever implemented the Mandelbrot set. –  Martin Büttner Aug 2 at 11:12
2  
As iconic as the full Mandelbrot set is (+1, by the way!), it looks like you've left yourself just enough room to adjust the parameters and post an answer with some of the stunningly twisted detail of a deep zoom. –  githubphagocyte Aug 2 at 12:28
1  
@githubphagocyte I already thought about that, but couldn't yet be bothered to recompile and rerun and convert every time until I've figured out decent parameters ;). Might do so later. First I've got to try a completely different function though. ;) –  Martin Büttner Aug 2 at 12:30
2  
@githubphagocyte finally got around to adding that. thanks for the suggestion! –  Martin Büttner Aug 2 at 20:00
2  
Thanks @Todd, I've updated the final picture with that. I used 25600 iterations, that too long enough. ;) –  Martin Büttner Aug 2 at 21:56

Julia sets

If there's a Mandelbrot, there should be a Julia set too.

enter image description here

You can spend hours tweaking the parameters and functions, so this is just a quick one that looks decent.

Inspired from Martin's participation.

unsigned short red_fn(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;}return log(n)*256;}

unsigned short green_fn(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;}return log(n)*128;}

unsigned short blue_fn(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;}return log(n)*128;}

Would you like some RNG?

OK, Sparr's comment put me on the track to randomize the parameters of these little Julias. I first tried to do bit-level hacking with the result of time(0) but C++ doesn't allow hexadecimal floating point litterals so this was a dead-end (with my limited knowledge at least). I could have used some heavy casting to achieve it, but that wouldn't have fit into the 140 bytes.

I didn't have much room left anyway, so I had to drop the red Julia to put my macros and have a more conventional RNG (timed seed and real rand(), woohoo!).

enter image description here

Whoops, something is missing. Obviously, these parameters have to be static or else you have some weird results (but funny, maybe I'll investigate a bit later if I find something interesting).

So here we are, with only green and blue channels:

enter image description here

enter image description here

enter image description here

Now let's add a simple red pattern to fill the void. Not really imaginative, but I'm not a graphic programer ... yet :-)

enter image description here

enter image description here

And finally the new code with random parameters:

unsigned short red_fn(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
return _cb(i^j);}

unsigned short green_fn(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;}return log(n)*512;}

unsigned short blue_fn(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;}return log(n)*512;}

There's still room left now ...

share|improve this answer
    
do you have room to randomize the parameters each run with srand(time(0) and rand()? or just time(0)? –  Sparr Aug 3 at 17:56
1  
That last one is going on my wall. –  cjfaure Aug 3 at 21:27
    
@Sparr updated with your suggestion. Had some fun :-). –  teh internets is made of catz Aug 3 at 21:28
    
@Trimsty Thanks! –  teh internets is made of catz Aug 3 at 21:28
3  
I can't tell what a like the most: your answer or your username –  William Barbosa Aug 5 at 11:02

Mandelbrot 3 x 133 chars

The first thing that popped into my mind was "Mandelbrot!".

Yes, I know there already is a mandelbrot submission. After confirming that I'm able to get it below 140 characters myself, I have taken the tricks and optimizations from that solution into mine (thanks Martin and Todd). That left space to choose an interesting location and zoom, as well as a nice color theme:

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

132 chars total

I tried to get it down to 140 for all 3 channels. There is a bit of color noise near the edge, and the location is not as interesting as the first one, but: 132 chars

mandelbrot-reduced

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);
}
share|improve this answer
5  
Those colours are gorgeous! –  Martin Büttner Aug 4 at 21:12
    
I love this one, best looking image yet! –  Roy van Rijn Aug 5 at 8:56
3  
This is my wallpaper now. –  Cipher Aug 6 at 9:20
    
For those interested I made a full wallpaper-sized render of this: i1.minus.com/ibdFPmIZlfH9FM.png . –  orlp Aug 11 at 3:17

Image

/* RED */
    int a=(j?i%j:i)*4;int b=i-32;int c=j-32;return _sq(abs(i-512))+_sq(abs(j-512))>_sq(384)?a:int(sqrt((b+c)/2))^_cb((b-c)*2);
/* GREEN */
    int a=(j?i%j:i)*4;return _sq(abs(i-512))+_sq(abs(j-512))>_sq(384)?a:int(sqrt((i+j)/2))^_cb((i-j)*2);
/* BLUE */
    int a=(j?i%j:i)*4;int b=i+32;int c=j+32;return _sq(abs(i-512))+_sq(abs(j-512))>_sq(384)?a:int(sqrt((b+c)/2))^_cb((b-c)*2);
share|improve this answer
2  
That is really beautiful, +1. –  Milo Aug 3 at 5:09
2  
This is my favorite. It looks like a professionally made piece of graphic design. :D –  cjfaure Aug 3 at 20:58
3  
It looks like a wafer of microprocessors. macrophotographer.net/images/ss_rvsi_5.jpg –  s0rce Aug 8 at 15:03
    
It looks like a minimalist wallpaper. –  A.L Aug 11 at 1:24

This one is interesting because it doesn't use the i, j parameters at all. Instead it remembers state in a static variable.

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

colorful

share|improve this answer
    
It would be interesting to see the results of this code on different platforms/compilers. The value of RAND_MAX varies widely and could give completely different images... –  githubphagocyte Aug 5 at 0:40
4  
It shouldn't change much. (double)rand()/RAND_MAX should always be in the range [0.0, 1.0]. –  Manuel Kasten Aug 5 at 6:16
1  
This is one of my favorites! –  Calvin's Hobbies Aug 6 at 0:23
1  
It is not only interesting - it is beautiful! –  moose Aug 8 at 4:48

I regret that my answer falls 183 bytes too large (and requires allowing code outside the functions). I could probably golf it down a bit more (by making the output less interesting, for example, I can immediately get it down to only 82 bytes over, which is well-within a single tweet's worth), but it's 01:15 now, and I figure I should sleep.

Without further ado, I present a distance-estimating, 3D fractal raytracer, rendering an implicitly defined, triplex-algebraic mandelbulb with per-pixel diffuse lighting and correct perspective projection: Mandelbulb

Inside the red function:

#define F float
#define L(X,Y,Z)sqrt(X*X+Y*Y+Z*Z)
#define N(X,Y,Z){F K=L(X,Y,Z);X/=K;Y/=K;Z/=K;}
return GR(i,j);

Between the red function and the green function:

F x,y,z,g,Q,W,E,X,Y,Z,J,A,B,C,r,R,V,S,T,P;F M(F x,F y,F z){A=x,B=y,C=z,R=1;for(int i=0;i<500;++i){r=L(A,B,C);if(r>6)break;T=acos(C/r)*8;P=atan(B/A)*8;R=pow(r,7)*8*R+1;V=pow(r,8);S=sin(T);A=V*S*cos(P)+x;B=V*S*sin(P)+y;C=V*cos(T)+z;}return log(r)*r/R/2;}

Inside the green function:

y=4,x=z=g=0,Q=(F)i/DIM-0.5,W=-1,E=(F)j/DIM-0.5;N(Q,W,E)while(g<10){J=M(x,y,z);g+=J;x+=J*Q;y+=J*W;z+=J*E;if(J<0.01){J=M(x,y,z);X=M(x+0.001,y,z)-J;Y=M(x,y+0.001,z)-J;Z=M(x,y,z+0.001)-J;N(X,Y,Z)return 255*fmax(0,-Z);}}return 0;

Inside the blue function:

return GR(i,j);

The ungolfed code:

#include <iostream>
#include <cmath>


#define DIM 256
#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 short)(pow((x),1.0/3.0))  // cube root

#define L(X,Y,Z) sqrt(X*X+Y*Y+Z*Z)
#define N(X,Y,Z) {float l=L(X,Y,Z);X/=l;Y/=l;Z/=l;}
float mandelbulb_de(float x,float y,float z, int n) {
        if (L(x,y,z)>7.0) return L(x,y,z)-6.0;

        float x2=x,y2=y,z2=z;
        float dr = 1.0;
        float r = 0.0; //initialization only to keep compiler happy

        #define POWER 8.0

        for (int i=0;i<n;++i) {
                r = L(x2,y2,z2);
                if (r>6.0) break;

                //convert to polar coordinates
                float theta = acos(z2/r);
                float phi = atan2(y2,x2);
                dr = pow(r,POWER-1.0)*POWER*dr + 1.0;

                //scale and rotate the point
                float zr = pow(r,POWER);
                theta *= POWER;
                phi *= POWER;

                //convert back to cartesian coordinates
                float s_theta = sin(theta);
                x2 = zr * s_theta*cos(phi) + x;
                y2 = zr * s_theta*sin(phi) + y;
                z2 = zr * cos(theta)       + z;
        }

        return 0.5*log(r)*r/dr;
}
unsigned char RD(int i,int j) {
        float x=0.0f, y=4.0f, z=0.0f;

        float dx = (float)(i)/DIM - 0.5f;
        float dz = (float)(j)/DIM - 0.5f;
        float dy = -1.0f;
        N(dx,dy,dz)

        float total = 0.0f;
        while (total<10.0f) {
                float d = mandelbulb_de(x,y,z,500);
                total += d;
                x += d * dx;
                y += d * dy;
                z += d * dz;
                if (d<=0.01f) {
                        //return 0xFFu*total/5.0;
                        float c = mandelbulb_de(x,y,z,500);
                        float nx = mandelbulb_de(x+0.001,y,z,500) - c;
                        float ny = mandelbulb_de(x,y+0.001,z,500) - c;
                        float nz = mandelbulb_de(x,y,z+0.001,500) - c;
                        N(nx,ny,nz)
                        return 0xFFu*fmax(0,-nz);
                }
        }
        return 0x00u;
}
unsigned char GR(int i,int j) {
        return RD(i,j);
}
unsigned char BL(int i,int j) {
        return RD(i,j);
}

FILE* fp;
void pixel_write(int i, int j){
        static unsigned char color[3];
        color[0] = RD(i,j)&DM1;
        color[1] = GR(i,j)&DM1;
        color[2] = BL(i,j)&DM1;
        fwrite(color, sizeof(unsigned char),3, fp);
}
int main(int argc, char* argv[]) {
        fp = fopen("MathPic.ppm","wb");
        fprintf(fp, "P6\n%d %d\n255\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;
}
share|improve this answer
9  
That's beautiful, but I think if you're leaving it beyond tweet size this should probably rather be a community wiki since it's technically not a valid answer (I didn't include the invalid images in my random painter either, but linked to them externally). –  Martin Büttner Aug 6 at 9:28
    
somethingabouttherules, but this one made my day! Got itchy fingers for hacking away on mandelbulb renderings now. –  ovenror Aug 6 at 10:00
    
Converted to wiki per suggestion of @MartinBüttner. –  Doorknob Aug 6 at 12:01
3  
@tbodt From what I can tell it's a ray marcher (commonly used for rendering 3D fractals), which is less complicated than a ray tracer. But still impressive. –  teh internets is made of catz Aug 8 at 9:38
2  
@tehinternetsismadeofcatz correct. Note that in this case since the Mandelbulb is an implicit surface, raytracing isn't an option. –  imallett Aug 9 at 15:26

Sierpinski Pentagon

You may have seen the chaos game method of approximating Sierpinski's Triangle by plotting points half way to a randomly chosen vertex. Here I have taken the same approach using 5 vertices. The shortest code I could settle on included hard coding the 5 vertices, and there was no way I was going to fit it all into 140 characters. So I've delegated the red component to a simple backdrop, and used the spare space in the red function to define a macro to bring the other two functions under 140 too. So everything is valid at the cost of having no red component in the pentagon.

unsigned char RD(int i,int j){
#define A int x=0,y=0,p[10]={512,9,0,381,196,981,827,981,DM1,381}
auto s=99./(j+99);return GR(i,j)?0:abs(53-int((3e3-i)*s+j*s)%107);}

unsigned char GR(int i,int j){static int c[DIM][DIM];if(i+j<1){A;for(int n=0;n<2e7;n++){int v=(rand()%11+1)%5*2;x+=p[v];x/=2;y+=p[v+1];y/=2;c[x][y]++;}}return c[i][j];}

unsigned char BL(int i,int j){static int c[DIM][DIM];if(i+j<1){A;for(int n=0;n<3e7;n++){int v=(rand()%11+4)%5*2;x+=p[v];x/=2;y+=p[v+1];y/=2;c[x][y]++;}}return c[i][j];}

Thanks to Martin Büttner for the idea mentioned in the question's comments about defining a macro in one function to then use in another, and also for using memoisation to fill the pixels in an arbitrary order rather than being restricted to the raster order of the main function.

pentagon

The image is over 500KB so it gets automatically converted to jpg by stack exchange. This blurs some of the finer detail, so I've also included just the top right quarter as a png to show the original look:

top right

share|improve this answer

Buddhabrot (+ Antibuddhabrot)

Edit: It's a proper Buddhabrot now!

Edit: I managed to cap the colour intensity within the byte limit, so there are no more falsely black pixels due to overflow.

I really wanted to stop after four... but...

enter image description here

This gets slightly compressed during upload (and shrunk upon embedding) so if you want to admire all the detail, here is the interesting 512x512 cropped out (which doesn't get compressed and is displayed in its full size):

enter image description here

Thanks to githubphagocyte for the idea. This required some rather complicated abuse of all three colour functions:

unsigned short RD(int i,int j){
    #define f(a,b)for(a=0;++a<b;)
    #define D float x=0,y=0
    static int z,m,n;if(!z){z=1;f(m,4096)f(n,4096)BL(m-4096,n-4096);};return GR(i,j);
}
unsigned short GR(int i,int j){
    #define R a=x*x-y*y+i/1024.+2;y=2*x*y+j/1024.+2
    static float c[DIM][DIM],p;if(i>=0)return(p=c[i][j])>DM1?DM1:p;c[j+DIM][i/2+DIM]+=i%2*2+1;
}
unsigned short BL(int i,int j){
    D,a,k,p=0;if(i<0)f(k,5e5){R;x=a;if(x*x>4||y*y>4)break;GR(int((x-2)*256)*2-p,(y-2)*256);if(!p&&k==5e5-1){x=y=k=0;p=1;}}else{return GR(i,j);}
}

There are some bytes left for a better colour scheme, but so far I haven't found anything that beats the grey-scale image.

The code as given uses 4096x4096 starting points and does up to 500,000 iterations on each of them to determine if the trajectories escape or not. That took between 6 and 7 hours on my machine. You can get decent results with a 2k by 2k grid and 10k iterations, which takes two minutes, and even just a 1k by 1k grid with 1k iterations looks quite nice (that takes like 3 seconds). If you want to fiddle around with those parameters, there are a few places that need to change:

  • To change the Mandelbrot recursion depth, adjust both instances of 5e5 in BL to your iteration count.
  • To change the grid resolution, change all four 4096 in RD to your desired resolution and the 1024. in GR by the same factor to maintain the correct scaling.
  • You will probably also need to scale the return c[i][j] in GR since that only contains the absolute number of visits of each pixel. The maximum colour seems to be mostly independent of the iteration count and scales linearly with the total number of starting points. So if you want to use a 1k by 1k grid, you might want to return c[i][j]*16; or similar, but that factor sometimes needs some fiddling.

For those not familiar with the Buddhabrot (like myself a couple of days ago), it's based on the Mandelbrot computation, but each pixel's intensity is how often that pixel was visited in the iterations of the escaping trajectories. If we're counting the visits during non-escaping trajectories, it's an Antibuddhabrot. There is an even more sophisticated version called Nebulabrot where you use a different recursion depth for each colour channel. But I'll leave that to someone else. For more information, as always, Wikipedia.

Originally, I didn't distinguish between escaping and non-escaping trajectories. That generated a plot which is the union of a Buddhabrot and an Antibuddhabrot (as pointed out by githubphagocyte).

unsigned short RD(int i,int j){
    #define f(a)for(a=0;++a<DIM;)
    static int z;float x=0,y=0,m,n,k;if(!z){z=1;f(m)f(n)GR(m-DIM,n-DIM);};return BL(i,j);
}
unsigned short GR(int i,int j){
    float x=0,y=0,a,k;if(i<0)f(k){a=x*x-y*y+(i+256.0)/512;y=2*x*y+(j+512.0)/512;x=a;if(x*x+y*y>4)break;BL((x-.6)*512,(y-1)*512);}return BL(i,j);
}
unsigned short BL(int i,int j){
    static float c[DIM][DIM];if(i<0&&i>-DIM-1&&j<0&&j>-DIM-1)c[j+DIM][i+DIM]++;else if(i>0&&i<DIM&&j>0&&j<DIM)return log(c[i][j])*110;
}

enter image description here

This one looks a bit like a faded photograph... I like that.

share|improve this answer
4  
I shall make this into a hat. –  cjfaure Aug 7 at 21:31
4  
I am truly astonished that you got this down to 3 lots of 140 bytes. The new buddabrot image is beautiful. –  githubphagocyte Aug 9 at 12:26
3  
This is really impressive. –  copumpkin Aug 10 at 18:19
    
The first one is really artful. Reminds me of jellyfish. +1 –  Igby Largeman Aug 12 at 2:19
    
This one is my favorite submission. Nice work! –  thomallen Aug 19 at 22:40

Sheet Music

Sierpinski music. :D The guys on chat say it looks more like the punched paper for music boxes.

Sheet music

unsigned short RD(int i,int j){
    return ((int)(100*sin((i+400)*(j+100)/11115)))&i;
}
unsigned short GR(int i,int j){
    return RD(i,j);
}
unsigned short BL(int i,int j){
    return RD(i,j);
}

Some details on how this works...um, it's actually just a zoom-in on a render of some wavy Sierpinski triangles. The sheet-music look (and also the blockiness) is the result of integer truncation. If I change the red function to, say,

return ((int)(100*sin((i+400)*(j+100)/11115.0)));

the truncation is removed and we get the full resolution render:

Non-blocky sheet music

So yeah, that's interesting.

share|improve this answer
1  
It's like Squarepusher transcribed into neumes –  squeamish ossifrage Aug 4 at 14:37
1  
@squeamishossifrage What did I just watch...? –  cjfaure Aug 4 at 14:46
    
:-) Chris Cunningham's videos are a bit odd, aren't they? –  squeamish ossifrage Aug 4 at 18:31
11  
the second one looks like it's moving when I scroll the page –  user13267 Aug 5 at 22:22
4  
In scrolling down the site, the last one really seemed to be moving. Nice optical illusion. –  Kyle Kanos Aug 6 at 16:02

The Lyapunov Fractal

Lyapunov Fractal

The string used to generate this was AABAB and the parameter space was [2,4]x[2,4]. (explanation of string and parameter space here)

With limited code space I thought this colouring was pretty cool.

    //RED
    float r,s=0,x=.5;for(int k=0;k++<50;)r=k%5==2||k%5==4?(2.*j)/DIM+2:(2.*i)/DIM+2,x*=r*(1-x),s+=log(fabs(r-r*2*x));return abs(s);
    //GREEN
    float r,s=0,x=.5;for(int k=0;k++<50;)r=k%5==2||k%5==4?(2.*j)/DIM+2:(2.*i)/DIM+2,x*=r*(1-x),s+=log(fabs(r-r*2*x));return s>0?s:0;
    //BLUE
    float r,s=0,x=.5;for(int k=0;k++<50;)r=k%5==2||k%5==4?(2.*j)/DIM+2:(2.*i)/DIM+2,x*=r*(1-x),s+=log(fabs(r-r*2*x));return abs(s*x);

I also made a variation of the Mandelbrot set. It uses a map similar to the Mandelbrot set map. Say M(x,y) is the Mandelbrot map. Then M(sin(x),cos(y)) is the map I use, and instead of checking for escaping values I use x, and y since they are always bounded.

//RED
float x=0,y=0;for(int k=0;k++<15;){float t=_sq(sin(x))-_sq(cos(y))+(i-512.)/512;y=2*sin(x)*cos(y)+(j-512.0)/512;x=t;}return 2.5*(x*x+y*y);
//GREEN
float x=0,y=0;for(int k=0;k++<15;){float t=_sq(sin(x))-_sq(cos(y))+(i-512.)/512;y=2*sin(x)*cos(y)+(j-512.0)/512;x=t;}return 15*fabs(x);
//BLUE
float x=0,y=0;for(int k=0;k++<15;){float t=_sq(sin(x))-_sq(cos(y))+(i-512.)/512;y=2*sin(x)*cos(y)+(j-512.0)/512;x=t;}return 15*fabs(y);

enter image description here

EDIT

After much pain I finally got around to creating a gif of the second image morphing. Here it is:

Party Time

share|improve this answer
10  
Nice psychedelic look for the second. –  teh internets is made of catz Aug 5 at 9:17
3  
These are insane! +1 –  cjfaure Aug 5 at 9:45
7  
Scary fractal is scary ༼ ༎ຶ ෴ ༎ຶ༽ –  Tobia Aug 7 at 18:50
1  
Holy shit that second is scary. Amaximg how much you can get out of the simple z=z^2+c. –  tomsmeding Aug 8 at 15:37
3  
If Edward Munch used to paint fractals, this would have been what The Scream looked like. –  teh internets is made of catz Aug 9 at 19:03

Random Voronoi diagram generator anyone?

OK, this one gave me a hard time. I think it's pretty nice though, even if the results are not so arty as some others. That's the deal with randomness. Maybe some intermediate images look better, but I really wanted to have a fully working algorithm with voronoi diagrams.

enter image description here

Edit:

enter image description here

This is one example of the final algorithm. The image is basically the superposition of three voronoi diagram, one for each color component (red, green, blue).

Code

ungolfed, commented version at the end

unsigned short red_fn(int i, int j){
int t[64],k=0,l,e,d=2e7;srand(time(0));while(k<64){t[k]=rand()%DIM;if((e=_sq(i-t[k])+_sq(j-t[42&k++]))<d)d=e,l=k;}return t[l];
}

unsigned short green_fn(int i, int j){
static int t[64];int k=0,l,e,d=2e7;while(k<64){if(!t[k])t[k]=rand()%DIM;if((e=_sq(i-t[k])+_sq(j-t[42&k++]))<d)d=e,l=k;}return t[l];
}

unsigned short blue_fn(int i, int j){
static int t[64];int k=0,l,e,d=2e7;while(k<64){if(!t[k])t[k]=rand()%DIM;if((e=_sq(i-t[k])+_sq(j-t[42&k++]))<d)d=e,l=k;}return t[l];
}

It took me a lot of efforts, so I feel like sharing the results at different stages, and there are nice (incorrect) ones to show.

First step: have some points placed randomly, with x=y

enter image description here

I have converted it to jpeg because the original png was too heavy for upload (>2MB), I bet that's way more than 50 shades of grey!

Second: have a better y coordinate

I couldn't afford to have another table of coordinates randomly generated for the y axis, so I needed a simple way to get " random " ones in as few characters as possible. I went for using the x coordinate of another point in the table, by doing a bitwise AND on the index of the point.

enter image description here

3rd: I don't remember but it's getting nice

But at this time I was way over 140 chars, so I needed to golf it down quite a bit.

enter image description here

4th: scanlines

Just kidding, this is not wanted but kind of cool, methinks.

enter image description here enter image description here

Still working on reducing the size of the algorithm, I am proud to present:

StarFox edition

enter image description here

Voronoi instagram

enter image description here

5th: increase the number of points

I have now a working piece of code, so let's go from 25 to 60 points. enter image description here

That's hard to see from only one image, but the points are nearly all located in the same y range. Of course, I didn't change the bitwise operation, &42 is much better:

enter image description here

And here we are, at the same point as the very first image from this post. Let's now explain the code for the rare ones that would be interested.

Ungolfed and explained code

unsigned short red_fn(int i, int j)
{
    int t[64],          // table of 64 points's x coordinate
        k = 0,          // used for loops
        l,              // retains the index of the nearest point
        e,              // for intermediary results
        d = 2e7;        // d is the minimum distance to the (i,j) pixel encoutnered so far
        // it is initially set to 2e7=2'000'000 to be greater than the maximum distance 1024²

    srand(time(0));     // seed for random based on time of run
    // if the run overlaps two seconds, a split will be observed on the red diagram but that is
    // the better compromise I found

    while(k < 64)       // for every point
    {
        t[k] = rand() % DIM;        // assign it a random x coordinate in [0, 1023] range
        // this is done at each call unfortunately because static keyword and srand(...)
        // were mutually exclusive, lenght-wise

        if (
            (e=                         // assign the distance between pixel (i,j) and point of index k
                _sq(i - t[k])           // first part of the euclidian distance
                +
                _sq(j - t[42 & k++])    // second part, but this is the trick to have "" random "" y coordinates
                // instead of having another table to generate and look at, this uses the x coordinate of another point
                // 42 is 101010 in binary, which is a better pattern to apply a & on; it doesn't use all the table
                // I could have used 42^k to have a bijection k <-> 42^k but this creates a very visible pattern splitting the image at the diagonal
                // this also post-increments k for the while loop
            ) < d                       // chekcs if the distance we just calculated is lower than the minimal one we knew
        )
        // {                            // if that is the case
            d=e,                        // update the minimal distance
            l=k;                        // retain the index of the point for this distance
            // the comma ',' here is a trick to have multiple expressions in a single statement
            // and therefore avoiding the curly braces for the if
        // }
    }

    return t[l];        // finally, return the x coordinate of the nearest point
    // wait, what ? well, the different areas around points need to have a
    // "" random "" color too, and this does the trick without adding any variables
}

// The general idea is the same so I will only comment the differences from green_fn
unsigned short green_fn(int i, int j)
{
    static int t[64];       // we don't need to bother a srand() call, so we can have these points
    // static and generate their coordinates only once without adding too much characters
    // in C++, objects with static storage are initialized to 0
    // the table is therefore filled with 60 zeros
    // see http://stackoverflow.com/a/201116/1119972

    int k = 0, l, e, d = 2e7;

    while(k<64)
    {
        if( !t[k] )                 // this checks if the value at index k is equal to 0 or not
        // the negation of 0 will cast to true, and any other number to false
            t[k] = rand() % DIM;    // assign it a random x coordinate

        // the following is identical to red_fn
        if((e=_sq(i-t[k])+_sq(j-t[42&k++]))<d)
            d=e,l=k;
    }

    return t[l];
}

Thanks for reading so far.

share|improve this answer
1  
I love Voronoi diagrams. +1 for fitting it in 3 tweets! –  Martin Büttner Aug 5 at 19:37
1  
This is one of my personal favorites. The scan line variants are very aesthetically pleasing. –  Fraxtil Aug 7 at 1:37
1  
Love how you explained the code –  Andrea Faulds Aug 10 at 22:19
    
Do a barrel roll! –  Starson Hochschild Aug 23 at 2:27

Because unicorns.

Because unicorns

I couldn't get the OPs version with unsigned short and colour values up to 1023 working, so until that is fixed, here is a version using char and maximum colour value of 255.

char red_fn(int i,int j){
    return (char)(_sq(cos(atan2(j-512,i-512)/2))*255);
}
char green_fn(int i,int j){
    return (char)(_sq(cos(atan2(j-512,i-512)/2-2*acos(-1)/3))*255);
}
char blue_fn(int i,int j){
    return (char)(_sq(cos(atan2(j-512,i-512)/2+2*acos(-1)/3))*255);
}
share|improve this answer

Diffusion Limited Aggregation

I've always been fascinated by diffusion limited aggregation and the number of different ways it appears in the real world.

I found it difficult to write this in just 140 characters per function so I've had to make the code horrible (or beautiful, if you like things like ++d%=4 and for(n=1;n;n++)). The three colour functions call each other and define macros for each other to use, so it doesn't read well, but each function is just under 140 characters.

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

diffusion limited aggregation

To visualise how the particles gradually aggregate, I produced snapshots at regular intervals. Each frame was produced by replacing the 1 in for(n=1;n;n++) with 0, -1<<29, -2<<29, -3<<29, 4<<29, 3<<29, 2<<29, 1<<29, 1. This kept it just under the 140 character limit for each run.

animated aggregation

You can see that aggregates growing close to each other deprive each other of particles and grow more slowly.


By making a slight change to the code you can see the remaining particles that haven't become attached to the aggregates yet. This shows the denser regions where growth will happen more quickly and the very sparse regions between aggregates where no more growth can occur due to all the particles having been used up.

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

DLA with visible particles

This can be animated in the same way as before:

animated aggregation with particles

share|improve this answer
3  
Very interesting, +1. –  teh internets is made of catz Aug 5 at 20:34

Logistic Hills

enter image description here

The functions

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

Ungolfed

All of the #defines are to fit BL under 140 chars. Here is the ungolfed version of the blue algorithm, slightly modified:

for(double a=0;a<DIM;a+=0.1){       // Incrementing a by 1 will miss points
    for(int b=0;b<DIM;b++){         // 1024 here is arbitrary, but convenient
        double r = a*(1.6/DIM)+2.4; // This is the r in the logistic bifurcation diagram (x axis)
        double x = 1.0001*b/DIM;    // This is x in the logistic bifurcation diagram (y axis). The 1.0001 is because nice fractions can lead to pathological behavior.
        for(int k=0;k<DIM;k++){
            x = r*x*(1-x);          // Apply the logistic map to x
            // We do this DIM/2 times without recording anything, just to get x out of unstable values
            if(k>DIM/2){
                if(c[(int)a][(int)(DM1*x)]<255){
                    c[(int)a][(int)(DM1*x)]+=0.01; // x makes a mark in c[][]
                } // In the golfed code, I just always add 0.01 here, and clip c to 255
            }
        }            
    }    
}

Where the values of x fall the most often for a given r (j value), the plot becomes lighter (usually depicted as darker).

share|improve this answer
3  
Aww, I was thinking about how to do this one yesterday. +1 for figuring it out. I actually thing the palette is really nice as it is! :) –  Martin Büttner Aug 7 at 7:14
2  
I stole the dirty tricks from you and githubphagocyte, though I take responsibility for the ugly #defines. Especially "#define G for(". –  Eric Tressler Aug 7 at 7:24
1  
looks more like a tournament bracket visualizer –  Kevin L Aug 7 at 16:50
3  
Not pictured at top: winner dies –  Eric Tressler Aug 7 at 17:48
1  
Can I get a poster-sized print of this? With 3 faded tweets in the background. :-) –  Andrew Cheong Aug 9 at 17:26

Edit: This is now a valid answer, thanks to the forward declarations of GR and BL.

Having fun with Hofstadter's Q-sequence! If we're using the radial distance from some point as the input and the output as the inverse colour, we get something which looks like coloured vinyl.

enter image description here

The sequence is very similar to the Fibonacci sequence, but instead of going 1 and 2 steps back in the sequence, you take the two previous values to determine how far to go back before taking the sum. It grows roughly linear, but every now and then there's a burst of chaos (at increasing intervals) which then settles down to an almost linear sequence again before the next burst:

enter image description here

You can see these ripples in the image after regions which look very "flat" in colour.

Of course, using only one colour is boring.

enter image description here

Now for the code. I need the recursive function to compute the sequence. To do that I use RD whenever j is negative. Unfortunately, that does not leave enough characters to compute the red channel value itself, so RD in turn calls GR with an offset to produce the red channel.

unsigned short RD(int i,int j){
    static int h[1000];return j<0?h[i]?h[i]:h[i]=i<2?1:RD(i-RD(i-1,j),j)+RD(i-RD(i-2,j),j):GR(i+256,j+512);
}
unsigned short GR(int i,int j){
    return DIM-4*RD(sqrt((i-512)*(i-512)+(j-768)*(j-768))/2.9,-1);
}
unsigned short BL(int i,int j){
    return DIM-4*RD(sqrt((i-768)*(i-768)+(j-256)*(j-256))/2.9,-1);
}

Of course, this is pretty much the simplest possible usage of the sequence, and there are loads of characters left. Feel free to borrow it and do other crazy things with it!

Here is another version where the boundary and the colours are determined by the Q-sequence. In this case, there was enough room in RD so that I didn't even need the forward declaration:

unsigned short RD(int i,int j){
    static int h[1024];return j<0?h[i]?h[i]:h[i]=i<2?1:RD(i-RD(i-1,j),j)+RD(i-RD(i-2,j),j):RD(2*RD(i,-1)-i+512>1023-j?i:1023-i,-1)/0.6;
}
unsigned short GR(int i,int j){
    return RD(i, j);
}
unsigned short BL(int i,int j){
    return RD(i, j);
}

enter image description here

share|improve this answer
    
Let us continue this discussion in chat. –  githubphagocyte Aug 2 at 13:51
    
That second grey-ish image is stunning! –  tomsmeding Aug 2 at 14:19
    
Can you compactify this enough to use the r/g/b functions themselves recursively, with invalid coordinates for the recursive calls? –  Sparr Aug 2 at 23:00
    
Converted to CW as noted by author that this isn't entirely valid. –  Doorknob Aug 6 at 12:39
    
And unwikified. –  Doorknob Aug 7 at 6:26

Spiral (140 exactly)

final product

This is 140 characters exactly if you don't include the function headers and brackets. It's as much spiral complexity I could fit in the character limit.

unsigned char RD(int i,int j){
    return DIM-BL(2*i,2*j);
}
unsigned char GR(int i,int j){
    return BL(j,i)+128;
}
unsigned char BL(int i,int j){
    i-=512;j-=512;int d=sqrt(i*i+j*j);return d+atan2(j,i)*82+sin(_cr(d*d))*32+sin(atan2(j,i)*10)*64;
}

I gradually built on a simple spiral, adding patterns to the spiral edges and experimenting with how different spirals could be combined to look cool. Here is an ungolfed version with comments explaining what each piece does. Messing with parameters can produce some interesting results.

unsigned char RD(int i,int j){
    // *2 expand the spiral
    // DIM- reverse the gradient
    return DIM - BL(2*i, 2*j);
}
unsigned char GR(int i,int j){
    // notice swapped parameters
    // 128 changes phase of the spiral
    return BL(j,i)+128;
}
unsigned char BL(int i,int j){
    // center it
    i -= DIM / 2;
    j -= DIM / 2;

    double theta = atan2(j,i); //angle that point is from center
    double prc = theta / 3.14f / 2.0f; // percent around the circle

    int dist = sqrt(i*i + j*j); // distance from center

    // EDIT: if you change this to something like "prc * n * 256" where n
    //   is an integer, the spirals will line up for any arbitrarily sized
    //   DIM value, or if you make separate DIMX and DIMY values!
    int makeSpiral = prc * DIM / 2;

    // makes pattern on edge of the spiral
    int waves = sin(_cr(dist * dist)) * 32 + sin(theta * 10) * 64;

    return dist + makeSpiral + waves;
}

Messing with parameters:

Here, the spirals are lined up but have different edge patterns. Instead of the blocky edges in the main example, this has edges entirely comprised of sin waves.

edges

Here, the gradient has been removed:

no gradient

An animation (which for some reason doesn't appear to be looping after I uploaded it, sorry. Also, I had to shrink it. Just open it in a new tab if you missed the animation):

animation

And, here's the imgur album with all images in it. I'd love to see if anyone can find other cool spiral patterns. Also, I must say, this is by far one of the coolest challenges on here I have ever seen. Enjoy!

EDIT: Here are some backgrounds made from these spirals with altered parameters.

Also, by combining my spiral edge patterns with some of the fractals I've seen on here through the use of xor/and/or operations, here is a final spiral:

fractal spiral

share|improve this answer
2  
These are fantastic! If you look around the other answers you might be able to find ideas to golf this down even further if you wanted more room. A few of the answers use #define in one function to define a macro that all 3 can use, so you can offload the bulk of the calculation into other colour functions. Martin Büttner introduced me to that trick. –  githubphagocyte Aug 8 at 22:49
    
Thank you! In my case, as far as I can find, my code lacks the kind of duplicate logic patterns which would benefit from pound defines. However, if you see any, I would appreciate if you would identify them to me, especially seeing I haven't used C/C++ extensively in years. –  xleviator Aug 9 at 0:36
    
Finding duplicate sections would indeed help even more, but even without any duplication you can simply move code from BL to RD or GN by defining it as a macro in RD or GN and then using it in BL. That should give you twice as much room for extra code. –  githubphagocyte Aug 9 at 1:44
    
Ah! I see. I didn't even realize that each function body itself had the 140 character limit. I suppose next time I should read the prompt more carefully. Thank you for pointing that out! –  xleviator Aug 9 at 1:46
1  
As was being discussed in the chat, your non-looping GIF should be easily fixable. I think it's worth doing as the brief bit of animation it currently shows looks great. –  githubphagocyte Aug 9 at 12:35

This calculates the Joukowsky transform of a set of concentric circles centred on a point slightly offset from the origin. I slightly modified the intensities in the blue channel to give a bit of colour variation.

unsigned short RD(int i,int j){
    double r=i/256.-2,s=j/256.-2,q=r*r+s*s,n=hypot(r+(.866-r/2)/q,s+(r*.866+s/2)/q),
    d=.5/log(n);if(d<0||d>1)d=1;return d*(sin(n*10)*511+512);
}
unsigned short GR(int i,int j){
    return 0;
}
unsigned short BL(int i,int j){
    double r=i/256.-2,s=j/256.-2,q=r*r+s*s;return RD(i,j)*sqrt(q/40);
}

enter image description here

share|improve this answer

Figured I'd play with this code's parameters... All credit goes to @Manuel Kasten. These are just so cool that I couldn't resist posting. Hot & Cold

/* RED */
double a=0,b=0,c,d,n=0;
while((c=a*a)+(d=b*b)<4&&n++<880){b=2*a*b+(j)*9e-9-.645411;a=c-d+(i)*9e-9+.356888;}
return 1000*pow((n)/800,.5);
/* GREEN */
double a=0,b=0,c,d,n=0;
while((c=a*a)+(d=b*b)<4&&n++<880){b=2*a*b+(j)*9e-9-.645411;a=c-d+(i)*9e-9+.356888;}
return 8000*pow((n)/800,.5);
/* BLUE */
double a=0,b=0,c,d,n=0;
while((c=a*a)+(d=b*b)<4&&n++<880){b=2*a*b+(j)*9e-9-.645411;a=c-d+(i)*9e-9+.356888;}
return 8000*pow((n)/800,.5);

BubbleGumRupture

/* RED */
double a=0,b=0,c,d,n=0;
while((c=a*a)+(d=b*b)<4&&n++<880){b=2*a*b+(j)*9e-9-.645411;a=c-d+(i)*9e-9+.356888;}
return 8000*pow((n)/800,.5);
/* GREEN */
double a=0,b=0,c,d,n=0;
while((c=a*a)+(d=b*b)<4&&n++<880){b=2*a*b+(j)*9e-9-.645411;a=c-d+(i)*9e-9+.356888;}
return 40*pow((n)/800,.5);
/* BLUE */
double a=0,b=0,c,d,n=0;
while((c=a*a)+(d=b*b)<4&&n++<880){b=2*a*b+(j)*9e-9-.645411;a=c-d+(i)*9e-9+.356888;}
return 10*pow((n)/800,.5);

SeussZoom

/* RED */
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-8-.645411;a=c-d+i*8e-8+.356888;}
return 2000*pow((n)/800,.5);
/* GREEN */
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-8-.645411;a=c-d+i*8e-8+.356888;}
return 1000*pow((n)/800,.5);
/* BLUE */
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-8-.645411;a=c-d+i*8e-8+.356888;}
return 4000*pow((n)/800,.5);

SeussEternalForest

/* RED */
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 2000*pow((n)/800,.5);
/* GREEN */
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 1000*pow((n)/800,.5);
/* BLUE */
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 4000*pow((n)/800,.5);
share|improve this answer
2  
Looks like Dr. Seuss to me. Very cool! –  DLosc Aug 7 at 21:36
2  
Haha, I actually named the bottom two files Seuss1 and Sueuss2 –  Kyle McCormick Aug 8 at 13:17

Tribute to a classic

V1: Inspired by DreamWarrior's "Be happy", this straightforward submission embeds a small pixel-art image in each colour channel. I didn't even have to golf the code!
V2: now with considerably shorter code & a thick black border isolating only the "game screen".
V3: spaceship, bullet, damaged aliens and blue border, oh my! Trying to aim for this, roughly.

// RED
#define g(I,S,W,M)j/128%8==I&W>>(j/32%4*16+i/64)%M&S[abs(i/4%16-8)-(I%2&i%64<32)]>>j/4%8&1
return g(1,"_\xB6\\\x98\0\0\0",255L<<36,64)?j:0;

// GREEN
#define S g(6,"\xFF\xFE\xF8\xF8\xF8\xF8\xF0\x0",1L<<22,64)|i/4==104&j/24==30
return g(2,"<\xBC\xB6}\30p\0\0",4080,32)|S?j:0;

// BLUE
return g(3,"_7\xB6\xFE\x5E\34\0",0x70000000FD0,64)|S|abs(i/4-128)==80&abs(j/4-128)<96|abs(j/4-128)==96&abs(i/4-128)<80?j:0;

Space invaders


I happened to stumble upon an edit by Umber Ferrule whose avatar inspired me to add another pixel-art-based entry. Since the core idea of the code is largely similar to the Space Invaders one, I'm appending it to this entry, though the two definitely had different challenging points. For this one, getting pink right (at the expense of white) and the fact that it's a rather big sprite proved nice challenges. The hexadecimal escapes (\xFF etc) in the red channel represent their corresponding characters in the source file (that is, the red channel in the source file contains binary data), whereas the octal escapes are literal (i.e. present in the source file).

// RED
#define g(S)(S[i/29%18*2+j/29/8%2]>>j/29%8&1)*DM1*(abs(i-512)<247&abs(j-464)<232)
return g("\xF3\xF2\xF2\x10\xF4\0\xF2\x10\xE1\xE0\x81\0\x80\0\x80\0\0\0\0\0@\0! \x03d8,=\x2C\x99\x84\xC3\x82\xE1\xE3");

// GREEN
return g(";\376z\34\377\374\372\30k\360\3\200\0\0\0\0\0\0\200\0\300\0\341 \373d\307\354\303\374e\374;\376;\377")? DM1 : BL(i,j)? DM1/2 : 0;

// BLUE
return g("\363\360\362\20\364\0\362\20\341\340\200\0\200\0\200\0\0\0\0\0\0\0\0\0\0\08\0<\0\230\0\300\0\341\340") / 2;

Bub (Bubble Bobble)

share|improve this answer
3  
I love this. Plenty of room to add extra features too... –  githubphagocyte Aug 10 at 23:45
1  
Yup, there's plenty of tricks to pull to reduce the size. I might give a go at extending it tomorrow. –  FireFly Aug 10 at 23:49
    
This is incredibly short now. Could you fit one of these bit patterns into the texture in your raycasting answer...? –  githubphagocyte Aug 11 at 1:37
    
@MartinBüttner oops, you're correct. I fixed it and made another update to the functions. –  FireFly Aug 11 at 8:44
    
Neat, I like how you took the 8x8 pixel art and "resized" it on the fly. However, I had to make a few changes and I'm still not getting exactly your image. I changed the 1L and 255L to 1LL and 255LL. Since that made it better, I am assuming you're probably compiling in 64bit mode and there's some bit width issues making the rest of my image come out wrong. But, still, nice job! –  DreamWarrior Aug 11 at 17:47

Objective-C

Rewrote the C++ code in Objective-C cos I couldn't get it to compile... It gave the same results as other answer when running on my iPad, so that's all good.

Here's my submission:

Triangles Galore

The code behind it is fairly simple:

unsigned short red_fn(int i,int j)
{
    return j^j-i^i;
}
unsigned short green_fn(int i,int j)
{
    return (i-DIM)^2+(j-DIM)^2;
}
unsigned short blue_fn(int i,int j)
{
    return i^i-j^j;
}

You can zoom in on squares by multiplying i and j by 0.5, 0.25 etc. before they are processed.

share|improve this answer
    
Are you sure that is the same code you used? The ^ look kind of odd, because (i^i) is always 0 (the XOR), and the ^2 looks more like a square than a XOR bit. –  Manuel Ferreria Aug 28 at 18:01
1  
@ManuelFerreria With the XOR, the code is actually compiled like this: x^(x-y)^y (this threw me off the first time too). If you have iOS capabilities, here's my code: gist.github.com/Jugale/28df46f87037d81d2a8f –  Jugale Aug 29 at 23:37

I feel compelled to submit this entry that I will call "undefined behavior", which will illustrate what your compiler does with functions that are supposed to return a value but don't:

unsigned short red_fn(int i,int j){}
unsigned short green_fn(int i,int j){}
unsigned short blue_fn(int i,int j){}

All black pixels:

all black pixels

Pseudo-random pixels:

pseudo-random pixels

And, of course, a host of other possible results depending on your compiler, computer, memory manager, etc.

share|improve this answer
1  
Which did you get? –  tomsmeding Aug 2 at 21:21
1  
I got solid black and solid color that changed between different runs of the program, with different compilers. –  Sparr Aug 2 at 21:39
5  
My compiler just errors and yells at me for not returning a value. –  Pharap Aug 6 at 16:04
1  
@Pharap that's not a bad thing :) –  Sparr Aug 9 at 22:19
    
I doubt you would ever get such nice randomness as your second picture suggests. A constant value, the index of the loop etc. are much more likely (whatever is stored inside EAX when the function is called). –  example Aug 11 at 12:55

Sierpinski Paint Splash

I wanted to play more with colors so I kept changing my other answer (the swirly one) and eventually ended up with this.

Sierpinski Paint Splash

unsigned short RD(int i,int j){
    return(sqrt(_sq(abs(73.-i))+_sq(abs(609.-j)))+1.)/abs(sin((sqrt(_sq(abs(860.-i))+_sq(abs(162.-j))))/115.)+2)/(115^i&j);
}
unsigned short GR(int i,int j){
    return(sqrt(_sq(abs(160.-i))+_sq(abs(60.-j)))+1.)/abs(sin((sqrt(_sq(abs(73.-i))+_sq(abs(609.-j))))/115.)+2)/(115^i&j);
}
unsigned short BL(int i,int j){
    return(sqrt(_sq(abs(600.-i))+_sq(abs(259.-j)))+1.)/abs(sin((sqrt(_sq(abs(250.-i))+_sq(abs(20.-j))))/115.)+2)/(115^i&j);
}

It's my avatar now. :P

share|improve this answer
1  
Good job. sir, good job. –  EaterOfCode Aug 6 at 9:50

groovy

groovy.png

Just some trigonometry and weird macro tricks.

RD:

#define I (i-512)
#define J (j-512)
#define A (sin((i+j)/64.)*cos((i-j)/64.))
return atan2(I*cos A-J*sin A,I*sin A+J*cos A)/M_PI*1024+1024;

GR:

#undef A
#define A (M_PI/3+sin((i+j)/64.)*cos((i-j)/64.))
return atan2(I*cos A-J*sin A,I*sin A+J*cos A)/M_PI*1024+1024;

BL:

#undef A
#define A (2*M_PI/3+sin((i+j)/64.)*cos((i-j)/64.))
return atan2(I*cos A-J*sin A,I*sin A+J*cos A)/M_PI*1024+1024;

EDIT: if M_PI isn't allowed due to only being present on POSIX-compatible systems, it can be replaced with the literal 3.14.

share|improve this answer
1  
I you've got spare characters, acos(-1) is a good replacement for M_PI. –  Martin Büttner Aug 6 at 12:23

Planetary Painter

//red
static int r[DIM];int p=rand()%9-4;r[i]=i&r[i]?(r[i]+r[i-1])/2:i?r[i-1]:512;r[i]+=r[i]+p>0?p:0;return r[i]?r[i]<DIM?r[i]:DM1:0;
//green
static int r[DIM];int p=rand()%7-3;r[i]=i&r[i]?(r[i]+r[i-1])/2:i?r[i-1]:512;r[i]+=r[i]+p>0?p:0;return r[i]?r[i]<DIM?r[i]:DM1:0;
//blue
static int r[DIM];int p=rand()%15-7;r[i]=i&r[i]?(r[i]+r[i-1])/2:i?r[i-1]:512;r[i]+=r[i]+p>0?p:0;return r[i]?r[i]<DIM?r[i]:DM1:0;

Inspired by Martin's obviously awesome entry, this is a different take on it. Instead of randomly seeding a portion of the pixels, I start with the top left corner as RGB(512,512,512), and take random walks on each color from there. The result looks like something from a telescope (imo).

Each pixel takes the average of the pixels above/left of it and adds a bit o' random. You can play with the variability by changing the p variable, but I think what I'm using is a good balance (mainly because I like blue, so more blur volatility gives good results).

There's a slight negative bias from integer division when averaging. I think it works out, though, and give a nice darkening effect to the bottom corner.

Of course, to get more than just a single result, you'll need to add an srand() line to your main function.

bands

share|improve this answer
2  
If the image were a bit larger, it'd look like rays of light. o: –  cjfaure Aug 7 at 8:02

I'm not good at math. I was always poor student at math class. So I made simple one.

mathpic1.png

I used modified user1455003's Javascript code. And this is my full code.

function red(x, y) {
    return (x + y) & y;
}

function green(x, y) {
    return (255 + x - y) & x;
}

function blue(x, y) {
    // looks like blue channel is useless
    return Math.pow(x, y) & y;
}

It's very short so all three functions fits in one tweet.


mathpic2.png

function red(x, y) {
    return Math.cos(x & y) << 16;
}

function green(x, y) {
    return red(DIM - x, DIM - y);
}

function blue(x, y) {
    return Math.tan(x ^ y) << 8;
}

Another very short functions. I found this sierpinski pattern (and some tangent pattern) while messing around with various math functions. This is full code

share|improve this answer
    
Just i&j renders the Sierpinski triangle actually. Which is awesome. –  cjfaure Aug 7 at 20:00

Binary Flash (C++)

Here's one I made with a modified version of your framework, since I apparently don't have a reasonable ppm viewer. This one uses lodepng. But first, the submission:

unsigned short red_fn(int i,int j){
    double a=DM1-sqrt(_sq(i-DIM/2)*_sq(j-DIM/2)/8);return a<0?0:a;
}
unsigned short green_fn(int i,int j){
    return (unsigned short)((i^j)/9*sqrt(_sq((i-DIM/2)/10.)*_sq((j-DIM/2)/10.)))%DM1/(1+3.*(i+j)/DIM);
}
unsigned short blue_fn(int i,int j){
    return i&(~_sq(i/(j/10+1))|j);
}

Binary Flash

(the quality of these uploads sucks apparently, so run the code yourself to see the result in its full glory)

Triangular Limbo

I thought it couldn't hurt to submit a second one, a (thorough) modification of Binary Flash. Behold.

unsigned short red_fn(int i,int j){
    return 256+128+( (int)(256*sin(5.*i/DIM*acos(-1)))^(int)(256*sin(5.*j/DIM*acos(-1))) )/(1+1.*(i+j)/DIM);
}
unsigned short green_fn(int i,int j){
    return (int)(sqrt((i&(j-i))^j)/9*sqrt(_sq((i-DIM/2)/10.)*_sq((j-DIM/2)/10.)))%DM1/(7-2.*(i+j)/DIM);
}
unsigned short blue_fn(int i,int j){
    return i<j?((int)sqrt(i*i+j*j)^(i&j/(i*j+1)))/2:(i&(j-i))^j;
}

Triangular Limbo

My framework is as follows: (C++ code)

#include <stdlib.h>
#include <math.h>
#include <vector>
#include "lodepng.h"
#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 short)(pow((x),1.0/3.0))  // cube root

//HERE COME YOUR FUNCTIONS

int main(){
    int i,j;
    std::vector<unsigned char> image;
    image.resize(4*DIM*DIM);
    for(j=0;j<DIM;j++){
        for(i=0;i<DIM;i++){
            image[4*(DIM*j+i)]=(double)(red_fn(i,j)&DM1)/DM1*255; //this is essentially the same as yours except that it transforms the [0,1023] range to [0,255] for lodepng
            image[4*(DIM*j+i)+1]=(double)(green_fn(i,j)&DM1)/DM1*255;
            image[4*(DIM*j+i)+2]=(double)(blue_fn(i,j)&DM1)/DM1*255;
            image[4*(DIM*j+i)+3]=255;
        }
    }
    lodepng::encode("MathPic.png",image,DIM,DIM);
    return 0;
}
share|improve this answer
1  
Thanks for your PNG version ! –  teh internets is made of catz Aug 3 at 0:15

Action Painting

I wanted to try recreating something similar to the work of Jackson Pollock - dripping and pouring paint over a horizontal canvas. Although I liked the results, the code was much too long to post to this question and my best efforts still only reduced it to about 600 bytes. So the code posted here (which has functions of 139 bytes, 140 bytes, and 140 bytes respectively) was produced with an enormous amount of help from some of the geniuses in chat. Huge thanks to:

for a relentless group golfing session.

unsigned char RD(int i,int j){
#define E(q)return i+j?T-((T-BL(i,j))*q):T;
#define T 255
#define R .1*(rand()%11)
#define M(v)(v>0&v<DIM)*int(v)
#define J [j]*250;
E(21)}

unsigned char GR(int i,int j){
#define S DIM][DIM],n=1e3,r,a,s,c,x,y,d=.1,e,f;for(;i+j<1&&n--;x=R*DM1,y=R*DM1,s=R*R*R*R,a=R*7,r=s*T)for(c=R;r>1;x+=s*cos(a),y+=s*sin
E(21)}

unsigned char BL(int i,int j){static float m[S(a),d=rand()%39?d:-d,a+=d*R,s*=1+R/99,r*=.998)for(e=-r;e++<r;)for(f=-r;f++<r;)m[M(x+e)*(e*e+f*f<r)][M(y+f)]=c;return T-m[i]J}

action painting 21, 21

The E(q) macro is used in the RD and GR functions. Changing the value of the argument changes the way the red and green components of the colours change. The J macro ends with a number which is used to determine how much the blue component changes, which in turn affects the red and green components because they are calculated from it. I've include some images with the red and green arguments of E varied to show the variety of colour combinations possible. Hover over the images for the red and green values if you want to run these yourself.

action painting 14, 14

action painting 63, 49

action painting 56, 42

action painting 0, 49

All of these images can be viewed at full size if you download them. The file size is small as the flat colour suits the PNG compression algorithm, so no lossy compression was required in order to upload to the site.

If you'd like to see images from various stages in the golfing process as we tried out different things, you can look in the action painting chat.

share|improve this answer
6  
I've been following this question and all the answers for a couple weeks now, and I have to say, this is the first one that made my jaw actually drop. HOLY AMAZINGNESS. I mean, all of the answers here are great — but this one is something I never would have expected to be possible. –  Todd Lehman Aug 14 at 18:47
1  
@ToddLehman thank you! This certainly isn't something I would be capable of alone - I know because I tried... –  githubphagocyte Aug 14 at 19:40
1  
AWESOME! One of the best in this question and for me the only one(maybe except winner) which looks like drawed by human :) –  cyriel Aug 18 at 19:24
    
@cyriel thanks very much. You could say this one was drawn by 5 humans... –  githubphagocyte Aug 18 at 21:31

protected by Community Aug 6 at 14:06

Thank you for your interest in this question. Because it has attracted low-quality answers, posting an answer now requires 10 reputation on this site.

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.