Zalgorithm

Print a Mandelbrot set to the console

A function to generate a Mandelbrot set:

import numpy as np

def mandelbrot_set(
    real_values: np.ndarray[np.float64],
    imag_values: np.ndarray[np.float64],
    max_iterations: int,
) -> list[int]:
    num_real = len(real_values)
    num_imag = len(imag_values)
    escape_counts = np.full((num_imag, num_real), max_iterations, dtype=int)
    for i, imag in enumerate(imag_values):
        for j, real in enumerate(real_values):
            z = complex(0, 0)
            c = complex(real, imag)

            for iter in range(max_iterations):
                if abs(z) > 2.0:
                    escape_counts[i][j] = iter
                    break
                else:
                    z = z * z + c
    return escape_counts

The function initializes a NumPy array with the value of max_iterations. Any complex numbers that diverge before max_iterations have their iteration counts recorded in the array.

Any numbers that do not diverge before max_iterations are considered to be in the Mandelbrot set. Note that this doesn’t prove that they are in the set. It’s possible that they would diverge given more iterations.

The mandelbrot_set function can be called with:

real = np.linspace(-2, 0.5, 20)
imag = np.linspace(1.25, -1.25, 20)

max_iterations = 50
result = mandelbrot_set(real, imag, max_iterations)
print(result)

Example output:

[[ 1  1  1  1  2  2  2  2  3  3  3  3  3  3  3  3  2  2  2  2]
 [ 1  1  1  2  2  2  3  3  3  3  3  3  4  4  6  4  3  3  2  2]
 [ 1  1  2  2  3  3  3  3  3  3  4  4  4  5  9 19  4  4  3  3]
 [ 1  1  2  3  3  3  3  3  3  4  4  4  5 26 19 11  5  4  4  3]
 [ 1  1  3  3  3  3  3  3  4  4  5  7  7 10 50 50  8  6  5  3]
 [ 1  2  3  3  3  3  3  4  5  5  6 25 50 50 50 50 50 13 28  4]
 [ 1  3  3  3  3  4  6  5  5  6 25 50 50 50 50 50 50 50  9  5]
 [ 1  3  4  4  5  6 12 10 10  9 50 50 50 50 50 50 50 50 50  6]
 [ 1  4  4  5  5  7 15 50 50 38 50 50 50 50 50 50 50 50 50  5]
 [ 1  5  7  6  8 45 50 50 50 50 50 50 50 50 50 50 50 50  9  5]
 [ 1  5  7  6  8 45 50 50 50 50 50 50 50 50 50 50 50 50  9  5]
 [ 1  4  4  5  5  7 15 50 50 38 50 50 50 50 50 50 50 50 50  5]
 [ 1  3  4  4  5  6 12 10 10  9 50 50 50 50 50 50 50 50 50  6]
 [ 1  3  3  3  3  4  6  5  5  6 25 50 50 50 50 50 50 50  9  5]
 [ 1  2  3  3  3  3  3  4  5  5  6 25 50 50 50 50 50 13 28  4]
 [ 1  1  3  3  3  3  3  3  4  4  5  7  7 10 50 50  8  6  5  3]
 [ 1  1  2  3  3  3  3  3  3  4  4  4  5 26 19 11  5  4  4  3]
 [ 1  1  2  2  3  3  3  3  3  3  4  4  4  5  9 19  4  4  3  3]
 [ 1  1  1  2  2  2  3  3  3  3  3  3  4  4  6  4  3  3  2  2]
 [ 1  1  1  1  2  2  2  2  3  3  3  3  3  3  3  3  2  2  2  2]]

The pattern defined by the value 50 is a small approximation of the Mandelbrot set.

Styling the output with Textualize Rich library #

Documentation: Textualize/rich

import numpy as np
from rich import print
from rich.panel import Panel
from rich import box

# ... same mandelbrot_set definition as in the code above

real = np.linspace(-2, 0.5, 20)
imag = np.linspace(1.25, -1.25, 20)

max_iterations = 50
result = mandelbrot_set(real, imag, max_iterations)


mandelbrot_repr = ""
for row in result:
    row_repr = ""

    for count in row:
        count_str = str(count)
        countstr_len = len(count_str)
        for char in range(4 - countstr_len):
            count_str += " "

        if count == max_iterations:  # allows for setting a specific color for the set
            color_code = 129
            style = "bold"
        else:
            color_code = count
            style = "bold"

        # it's convenient that standard terminal color codes can be used:
        count_str = (
            f"[color({color_code}) {style}]{count_str}[/color({color_code}) {style}]"
        )
        row_repr += count_str

    mandelbrot_repr += f"{row_repr}\n"

print(Panel(mandelbrot_repr, title="Mandelbrot set", expand=False, box=box.DOUBLE_EDGE))

Output in the terminal (the colors aren’t preserved when copied and pasted to this note):

╔═════════════════════════════════ Mandelbrot set ═════════════════════════════════╗
║ 1   1   1   1   2   2   2   2   3   3   3   3   3   3   3   3   2   2   2   2    ║
║ 1   1   1   2   2   2   3   3   3   3   3   3   4   4   6   4   3   3   2   2    ║
║ 1   1   2   2   3   3   3   3   3   3   4   4   4   5   9   19  4   4   3   3    ║
║ 1   1   2   3   3   3   3   3   3   4   4   4   5   26  19  11  5   4   4   3    ║
║ 1   1   3   3   3   3   3   3   4   4   5   7   7   10  50  50  8   6   5   3    ║
║ 1   2   3   3   3   3   3   4   5   5   6   25  50  50  50  50  50  13  28  4    ║
║ 1   3   3   3   3   4   6   5   5   6   25  50  50  50  50  50  50  50  9   5    ║
║ 1   3   4   4   5   6   12  10  10  9   50  50  50  50  50  50  50  50  50  6    ║
║ 1   4   4   5   5   7   15  50  50  38  50  50  50  50  50  50  50  50  50  5    ║
║ 1   5   7   6   8   45  50  50  50  50  50  50  50  50  50  50  50  50  9   5    ║
║ 1   5   7   6   8   45  50  50  50  50  50  50  50  50  50  50  50  50  9   5    ║
║ 1   4   4   5   5   7   15  50  50  38  50  50  50  50  50  50  50  50  50  5    ║
║ 1   3   4   4   5   6   12  10  10  9   50  50  50  50  50  50  50  50  50  6    ║
║ 1   3   3   3   3   4   6   5   5   6   25  50  50  50  50  50  50  50  9   5    ║
║ 1   2   3   3   3   3   3   4   5   5   6   25  50  50  50  50  50  13  28  4    ║
║ 1   1   3   3   3   3   3   3   4   4   5   7   7   10  50  50  8   6   5   3    ║
║ 1   1   2   3   3   3   3   3   3   4   4   4   5   26  19  11  5   4   4   3    ║
║ 1   1   2   2   3   3   3   3   3   3   4   4   4   5   9   19  4   4   3   3    ║
║ 1   1   1   2   2   2   3   3   3   3   3   3   4   4   6   4   3   3   2   2    ║
║ 1   1   1   1   2   2   2   2   3   3   3   3   3   3   3   3   2   2   2   2    ║
║                                                                                  ║
╚══════════════════════════════════════════════════════════════════════════════════╝

Textual representation of a small Mandelbrot set
Textual representation of a small Mandelbrot set

40x40 Mandelbrot set
40x40 Mandelbrot set

Pushing max_iterations to 200:

Mandelbrot set with max iterations set to 200
Mandelbrot set with max iterations set to 200

A 50x50 set with the spaces removed around three digit iteration counts, so that it renders close to the actual proportions of the real and imaginary domains:

Text representation of a 50x50 Mandelbrot set, max iterations: 220
Text representation of a 50x50 Mandelbrot set, max iterations: 220