3

I'm new to python and i've become very interested in it's ability to produce fractal images. I've written a few simple ones myself, but I just discovered a script for Mandelbrot fractals... it produces beautiful, full color images at your desired resolution.... but the code is obfuscated to look like ASCII art of a Mandelbrot.... really cool, but silly if you want to read it easily. It contains functions I haven't learned yet in python, so if someone can indent the script to look like normal python script, that'd be great. The script:

_                                      =   (
                                        255,
                                      lambda
                               V       ,B,c
                             :c   and Y(V*V+B,B,  c
                               -1)if(abs(V)<6)else
               (              2+c-4*abs(V)**-0.4)/i
                 )  ;v,      x=7200,4800;C=range(v*x
                  );import  struct;P=struct.pack;M,\
            j  ='<QIIHHHH',open('M.bmp','wb').write
for X in j('BM'+P(M,v*x*3+26,26,12,v,x,1,24))or C:
            i  ,Y=_;j(P('BBB',*(lambda T:(T*80+T**9
                  *i-950*T  **99,T*70-880*T**18+701*
                 T  **9     ,T*i**(1-T**45*2)))(sum(
               [              Y(0,(A%3/3.+X%v+(X/v+
                               A/3/3.-x/2)/1j)*2.5
                             /x   -2.7,i)**2 for  \
                               A       in C
                                      [:9]])
                                        /9)
                                       )   )

As I said, the art is cool, but too hard to read! If someone can do this, I'd be greatly thankful.

Lillz
  • 283
  • 2
  • 5
  • 19
  • 1
    I'd suggest using [PythonTidy](https://pypi.python.org/pypi/PythonTidy). – martineau Aug 04 '14 at 17:01
  • Even tidied up, the inner loop on this baby is using one very long expression. – Martijn Pieters Aug 04 '14 at 17:03
  • Since the point of obfuscation is to confuse and bewilder, it also likly that the variable names are meaningless or even misleading. Personally I think you'd be better off spending your time learning about the math involved in computing fractals -- it's not really that hard -- than trying to decipher this monstrosity. – martineau Aug 04 '14 at 17:09
  • 1
    Yeah, I see that... I think this one was submitted to make a Mandelbrot in as few lines as possible... I've found others, but none that I've seen use color gradients like this. Anyone know of any that can make Mandelbrots very similar to this? @martineau Do you know what method he is using to get the color gradient? If I knew that, I could program the actual math bit fairly easily – Lillz Aug 04 '14 at 17:10
  • Colours seem to be a function of the value of the first few iterations, directly colour coded into the BMP specification. I would use Matplotlib, just generate an array with the values and let the colourmap figure out the rest. – Davidmh Aug 04 '14 at 22:41
  • I think you posted this on the wrong site. http://codegolf.stackexchange.com/ – Stephan Dollberg Aug 04 '14 at 23:12
  • A color gradient in RGB looks complicated, but i ll'give it a try. I have done a gradient with a single color at most, just normalize the color range between 0 and 1 by dividing it bt max_Iterations, then apply a power to it (**12 worked for me) then multiply back by max_Iterations. Here is my code, it displays the set in Tkinter in a few seconds, https://code.activestate.com/recipes/579048-python-mandelbrot-fractal-with-tkinter/ – Antoni Gual Via Apr 24 '15 at 05:02
  • About coloring, here's the link to the page about coloring in Robert Munafo's Mandelbrot page http://mrob.com/pub/muency/color.html – Antoni Gual Via Apr 24 '15 at 10:37

1 Answers1

3

Note: This is not meant as a definitive answer, but as an effort for a step-by-step de-obfuscation. If you can provide an additional step to make things clearer, it would be great if you could add it to this answer.

Okay, let's start by giving the code proper newlines and indentation:

_ = (255,
    lambda V, B, c: c and Y(V*V + B, B, c-1) if(abs(V) < 6) else (2 + c - 4 * abs(V)**-0.4)/i)
v, x = 7200, 4800
C = range(v*x)
import struct
P=struct.pack
M, j = '<QIIHHHH', open('M.bmp','wb').write
for X in j('BM' + P(M, v*x*3+26, 26, 12, v, x, 1, 24)) or C:
    i, Y = _
    j(
        P('BBB',
                *(lambda T: (T * 80 + T**9 * i - 950 * T**99, T*70 - 880* T**18 + 701* T**9, T* i**(1-T**45*2)))(
                    sum([Y(0, (A%3/3. + X%v + (X/v + A/3/3. - x/2)/1j) * 2.5/x - 2.7, i)**2 for A in C[:9]]) / 9
                )
        )
    )

A bit better, but still confusing. For example, defining P as an alias for struct.pack, and all those two-declarations-in-one lines. If we get rid of them, and move the lambda definition outside the loop, we get this:

import struct
i = 255
Y = lambda V, B, c: c and Y(V*V + B, B, c-1) if(abs(V) < 6) else (2 + c - 4 * abs(V)**-0.4)/i
v = 7200
x = 4800
C = range(v*x)
M = '<QIIHHHH'
color = lambda T: (T * 80 + T**9 * i - 950 * T**99, T*70 - 880* T**18 + 701 * T**9, T * i**(1-T**45*2))

f = open('M.bmp','wb')
for X in f.write('BM' + struct.pack(M, v*x*3+26, 26, 12, v, x, 1, 24)) or C:
    f.write(
        struct.pack('BBB',
            *color(sum([Y(0, (A%3/3. + X%v + (X/v + A/3/3. - x/2)/1j) * 2.5/x - 2.7, i)**2 for A in C[:9]]) / 9))
    )

Things are starting to get a bit clearer now. The loop is writing color values for each pixel, and the lambda returns a 3-tuple, representing the blue, green and red values of each pixel.

import struct
i = 255
Y = lambda V, B, c: c and Y(V*V + B, B, c-1) if abs(V) < 6 else (
                    (2 + c - 4 * abs(V)**-0.4)/i)
v = 7200
x = 4800
C = range(v*x)
M = '<QIIHHHH'
color = lambda T: (T * 80 + T**9 * i - 950 * T**99,
                   T*70 - 880* T**18 + 701 * T**9,
                   T * i**(1-T**45*2))
f = open('M.bmp', 'wb')
for X in f.write('BM' + struct.pack(M, v*x*3+26, 26, 12, v, x, 1, 24)) or C:
    f.write(struct.pack('BBB',
        *color(sum(
            [Y(0, (A%3/3. + X%v + (X/v + A/3/3. - x/2)/1j) * 2.5/x - 2.7, i)**2
                for A in C[:9]]) / 9))
    )

As per your comment, the asterisk (the star, *) unpacks a list into an argument list.

After many hours, here's the nearly 100 MB image produced of the Mandelbrot set:

Mandelbrot set

martineau
  • 119,623
  • 25
  • 170
  • 301
Carsten
  • 17,991
  • 4
  • 48
  • 53
  • This is better... What does ` – Lillz Aug 04 '14 at 22:07
  • @Lillz [`struct.pack`](https://docs.python.org/2/library/struct.html) converts Python numbers into a representation of a C bynary data. ` – Davidmh Aug 04 '14 at 22:57
  • Carsten: If you made your answer a community wiki, others might be more inclined to work on it. – martineau Aug 05 '14 at 15:56
  • Ah this is definitely better. I'm still not to the point where I can understand the lambda function, but being able to read the code clearly is great. – Lillz Aug 05 '14 at 16:32
  • @martineau That was the plan, but I didn't notice the button and thought the only way to create a community wiki was the automatic way, by having it edited by 5 people. Also, nice image. :) – Carsten Aug 05 '14 at 17:14