Tweetable Mathematical Art

  • 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

    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 I was considering allowing other languages, but I'd have to require that whoever chose to do so would have to implement a nearly identical framework. I chose to make it this way to make it easier & quicker for people to work out a quick solution, rather than making it a more in-depth problem.

    @algorithmshark Edited to allow other languages.

    @Kyle I've tried both your examples, but both give a different image to what you've shown and the second one raises a division-by-zero error that I fixed with `i|j`->`i&&j`. Mind looking at it?

    Just to be absolutely clear, each function body can be up to 140 characters? The three added together can be more than 140 characters?

    @KyleMcCormick Do you consider it cheating to define a macro in `red_fn` and use it in `green_fn` and `blue_fn`?

    Am I right in thinking that the function body doesn't include the enclosing braces?

    @MartinBüttner your macro question makes me wonder if it is acceptable to call, for example, red_fn from green_fn, with two arguments that don't necessarily relate to pixel coordinates.

    @tomsmeding yes I believe you're right. I think I made that change (&& to |) without really thinking about it. Fixing it now.

    @MartinBüttner Feel free to do whatever you want in the space between the braces, but please do not change the function signature or write any external functions to call inside these. Also, changing to allow complex.h.

    @githubphagocyte We'll say the opening/closing braces don't count toward your 140 char count.

    @KyleMcCormick could you maybe add forward-declarations of the three colour functions to your framework? that would allow some funky mutual recursion. also, people porting the framework to other languages will get those capabilities for free anyway.

    @MartinBüttner That sounds interesting. I'd say that isn't really in the scope of what I was looking for... but I'm curious. Updating it now. Show me what you got!

    If you are going to add forward declarations and allow mutual recursion, is there any chance you could also shorten the function names, for example `r()` instead of `red_fn()`?

    Haha good call. Just a few minutes here...

    To the close voters calling this too broad, please try writing an answer to this first. It's surprisingly restrictive...

    This is my favorite thing I've seen on here in, like, ever!

    I love that this question feels like an old-school demo scene.

    For those using the unsigned short (non-alternative) version of this, what are you using to display the results? Neither my version of Gimp (2.2.13) nor ImageMagick's display (6.2.8) seem to like PPM files w/ 1023 as a max. Many of these answers don't seem to work at all with the alternative version (and some produce severe palette shifts with it).

    ImageMagick should work. Didn't try display, but convert was fine. On little endian systems you might need a htons() to write the color values like so: color[0] = htons(RD(i,j)&DM1); The 16bit ppm format is big endian. Declaration of htons is in arpa/inet.h

    @ManuelKasten tried that, still didn't produce an equivalent image. However, it is required on my machine, and thus did produce more sensible images! So thanks -- don't know why I didn't think of that, though I looked up the PPM format and didn't see endian-ness listed, so maybe that's why :-).

    Ugh, I didn't see it, but it was listed, haha.... Anyway, the fact remains that the answers using short still don't produce what their sample images show. For example, faubiguy's answer is just a black and white image of a gradient circle with a smooth diagonal gradient behind it. And cjfaure's answer is just a black canvas (though without the proper byte-order I get color). Oh well, I guess them's the brakes.

    I just wanted to say that these are amazing.

    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.

    I wonder what happens when you combine all the submissions o:

    Wow. 15 minutes writing an answer for this is prettier than 15 hours of hard work in MS Paint.

    I'm curious if you considered just using GLSL and http://glsl.heroku.com or http://shadertoy.com. The cool thing is their viewable online. Just provide a template, allow 140 chars in the middle of say `void main() { /* insert 140 chars here */ };`

    I whipped together a website to mess around with this kind of thing. You can't just paste in the examples, but I've initialized it with one of them so you can see how it's done. Scroll down to edit the functions. Site: http://qiemem.github.io/mathart/ Repo: https://github.com/qiemem/mathart

    @cjfaure The average of all the entries so far is https://i.imgur.com/4kqgQ5l.png - I combined them via Image Magick's convert tool (`convert.exe -average *.jpg average.png`)

    @gman I played around with things akin to this in MrDoob's GLSL sandbox a year or two ago. Another handy benefit is the live feedback while editing the code. And I agree, I'd enjoy that as well.

    Although I'm grateful, please don't accept the tablecloths answer. Even today there are still new votes coming in with more interesting answers bubbling their way towards the top. I encourage sorting by oldest and seeing how the answers developed over time, and having the highest voted pinned to the top will only serve to skew the voting further.

    The tablecloths answer is my least favourite among my own answers to this question, and certainly can't compare to some of the amazing answers by others.

    @trichoplax I agree with your first comment, but I decided to choose Manuel Kasten' s blue mandelbrot, because I've been using it as one of my backgrounds ever since he posted it. I didn't want to choose something with too few votes seeing as I tagged it as a "popularity contest"

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

    Those colours are gorgeous!

    I love this one, best looking image yet!

    This is my wallpaper now.

License under CC-BY-SA with attribution


Content dated before 6/26/2020 9:53 AM