Twitterable Mandelbrot II: The Mandelbrottening

No Gravatar

Yesterday I posted my Twitterable Mandelbrot, a ruby script that generates the Mandelbrot Set in 134 characters. A few of you took this as a challenge to shorten my code even further. I didn’t mind, and in fact was interested to see your results; I was sure that an extra character here or there could be shaved off.

What I didn’t expect at all was that somebody would shave fourteen characters off.

Reader brahbur on rubyflow came up with this:

a couple of these changes could be considered “cheating” (-:

80.times{|a|p (0..300).map{|b|x=y=i=0;(x,y,i=x*x-y*y+b/150.0-1.5,2*x*y+a/40.0-1,i+1)until(x*x+y*y>4||i>98);i>98?0:1}*''}

Brahbur’s solution does look different; there are quote marks on each line and it outputs 1s and 0s instead of #s and .s, but the mandelbrot is still clearly visible (Edit: I reduced the size from 300×80 to 240×60 just to keep the outputs roughly the same size):


Click for larger version (1400×800)

I think this is just awesome. Once we’re playing with 0′s and 1′s, I can see another optimization: i>98?0:1 can be replaced with 99<=>i. This bring us down to 118:

60.times{|a|p (0..240).map{|b|x=y=i=0;(x,y,i=x*x-y*y+b/120.0-1.5,2*x*y+a/30.0-1,i+1)until(x*x+y*y>4||i>98);99<=>i}*''}

I have to give most of the credit to brahbur, though–I just saw a tiny tweak, on top of the amazing rewrite they already did. So great. THANK YOU brahbur!

Now, the challenge continues: can you shorten this further? Brahbur was concerned about “cheating”, so let’s define the rules for clarity: Output should be 240×60 (extra quotes and padding are okay) and it should be visually recognizable as a Mandelbrot set. Other than that, go for it.

  1. Mike Woodhouse

    1.8.6 (and IronRuby, FWIW) both throw an error with the latest greatest – it looks like something to do with operator precedence: there’s a “don’t put space before argument parenthesis” that suggests it’s seeing the “(0..240)” as the parameter to “p”. Replacing that space with a “(” and inserting an extra “)” at a cost of one character fixes it:

    60.times{|a|p((0..240).map{|b|x=y=i=0;(x,y,i=x*x-y*y+b/120.0-1.5,2*x*y+a/30.0-1,i+1)until(x*x+y*y>4||i>98);99i}*”)}

    I’m assuming 1.9 is quite happy, in which case the code clearly demonstrates that 1.9 is at least one character more efficient…

    Should anyone be interested, IronRuby (the new 1.0 version) was waaaay faster on my (WinXPSP3 2GHz Xeon) machine: 1.35 seconds vs 9.02 for MRI 1.8.6. It may mean something, but then again it may not.

    • Yeah, I noticed that. 1.8.7 works, and 1.9.1 works. Jeremiah’s version doesn’t run under 1.8.7 either; I haven’t tried 1.9.1 yet.

      One of the drawbacks to code golf is that you statically force as many things as possible–including versions and, in some cases, even patch levels. :-)

  2. Got it down to 110:

    60.times{|a|puts (0..240).map{|b|x=i=0;x=x*x+Complex(b/4.0-45,a-30)/30until x.abs>4||9999?’#':’.'}*”}

    And the “cheating” version down to 101:

    60.times{|a|p (0..240).map{|b|x=i=0;x=x*x+Complex(b/4.0-45,a-30)/30until x.abs>4||98<i+=1;99i}*”}

    • I think wordpress doesn’t like that comparison operator? It should be:

      60.times{|a|puts (0..240).map{|b|x=i=0;x=x*x+Complex(b/4.0-45,a-30)/30until x.abs>4||99<i+=1;i>99?’#':’.'}*”}

      And:

      60.times{|a|p (0..240).map{|b|x=i=0;x=x*x+Complex(b/4.0-45,a-30)/30until x.abs>4||98<i+=1;99<=>i}*”}

Leave a Comment


NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>