I felt like it’s about time I tackled the Mandelbrot and Julia sets, in Ascii-Art. Heck, the Mandelbrot fractal is on the logo of this Blog! However, being the most well-known fractal, this issue was tackled already, with satisfactory results.

Still, I took the ten minutes required to draw them in Python, using numpy:

def get_mandelbrot(x, num_iter = 10):
c = x
for i in range(num_iter):
x = x**2 + c
return abs(x)>2
def get_julia(x, c, num_iter = 10):
for i in range(num_iter):
x = x**2 + c
return abs(x)>2 |

def get_mandelbrot(x, num_iter = 10):
c = x
for i in range(num_iter):
x = x**2 + c
return abs(x)>2
def get_julia(x, c, num_iter = 10):
for i in range(num_iter):
x = x**2 + c
return abs(x)>2

“Hey!” you might say, “There’s no loop in here!”. Indeed, with numpy loops can sometimes be avoided, when using arrays. When the expression x**2 + c is applied to an array x, it is applied element-wise, allowing for implicit loops. The actual magic happens in the following function:

def get_board(bottom_left, top_right, num_x, num_y):
x0, y0 = bottom_left
x1, y1 = top_right
x_values = numpy.arange(x0, x1, (x1-x0)/float(num_x))
y_values = numpy.arange(y0, y1, (y1-y0)/float(num_y))
return numpy.array([[x+1j*y for x in x_values] for y in y_values]) |

def get_board(bottom_left, top_right, num_x, num_y):
x0, y0 = bottom_left
x1, y1 = top_right
x_values = numpy.arange(x0, x1, (x1-x0)/float(num_x))
y_values = numpy.arange(y0, y1, (y1-y0)/float(num_y))
return numpy.array([[x+1j*y for x in x_values] for y in y_values])

The result of get_board will be used as the “x input” later on. It should be noted though that while that’s a cute trick this time, it might grow unhandy for more complicated computations. For example, making each element to reflect the iteration number on which it “escaped”.

So, here are the results:

############################ ##############
########################### ###############
########################## ##############
##################### ########
#################### #########
############ ####### ########
############ ########
######### #########
######### #########
############ ########
############ ####### ########
#################### #########
##################### ########
########################## ##############
########################### ###############
############################################################
############################################################
############################################################
############################ ###############################
######################### ## #############################
############## ####### ###########################
######## ## ### ########## ##############
######### ### ### ###### #############
############## ###### ### ### ########
############### ########## ### ## #######
############################ ####### #############
############################## ## ########################
################################ ###########################
############################################################
############################################################

Here’s the code. (With the usual bsd-license slapped on top of it :)