J.P. Larocque (jp_larocque) wrote,
J.P. Larocque
jp_larocque

Diversions: character Mandelbrot in Common Lisp

Mandelbrot in Common Lisp, rendered with textual characters:

Snoopy swearing

(defun mandelbrot (width height x-offset y-offset x-scale y-scale)
  (declare (optimize speed (space 0) (compilation-speed 0)))
  (labels ((mandelbrot (x-coord y-coord)
             (let ((max-iter 100))
               (loop for x = x-coord then next-x
                     for y = y-coord then next-y
                     for next-x = (+ (* x x) (* -1 y y) x-coord)
                     for next-y = (+ (* 2 x y) y-coord)
                     for iter from 0 below max-iter
                     unless (< (+ (* x x) (* y y)) 4)
                     doing (return (color iter))
                     finally (return #\Space))))
           (color (iter)
             (let ((iter-mixed (if (evenp iter) (1+ iter) (1- iter))))
               (code-char (+ 33 (mod iter-mixed 94)))))
           (draw (width height)
             (let* ((type 'float)
                    (x-offset (coerce (- x-offset (/ 1 x-scale 2)) type))
                    (y-offset (coerce (- y-offset (/ 1 y-scale 2)) type))
                    (x-res (coerce (/ 1 width x-scale) type))
                    (y-res (coerce (/ 1 height y-scale) type))
                    (crosshair-x (round (/ width 2)))
                    (crosshair-y (round (/ height 2))))
               (loop for y from y-offset by y-res
                     for y-px from 0 below height
                     doing (fresh-line)
                     doing (loop for x from x-offset by x-res
                                 for x-px from 0 below width
                                 doing (princ (cond ((and (= y-px crosshair-y)
                                                          (= x-px (1- crosshair-x)))
                                                     #\[)
                                                    ((and (= y-px crosshair-y)
                                                          (= x-px crosshair-x))
                                                     #\+)
                                                    ((and (= y-px crosshair-y)
                                                          (= x-px (1+ crosshair-x)))
                                                     #\])
                                                    (t (mandelbrot x y)))))))))
    (declare (inline mandelbrot color))
    (draw (* width 2) height)
    (values)))
  • Post a new comment

    Error

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 4 comments
shiny.
That's kind of disturbing. I like it.

Anonymous

January 6 2008, 02:41:19 UTC 9 years ago

What's a good initial value for the function?

width and height specify the size of the canvas, in characters. So, try 20 for instance. (width is first multiplied by 2, to make the "pixel" aspect ratio roughly 1:1.) Start with x-offset and y-offset at 0, and x-scale and y-scale at 1.