Patrick the purple dragon

dragoncoder047’s blog

random thoughts about nonrandom things

Lisp Practice

← Previous: uLisp Thoughts Next: ParTcl
Posted
By dragoncoder047
Category: lisp

Today I decided I would have a little fun with Lisp. I wanted to try and make a program that you can type in a function and get a graph of it.

I started off with a function that takes an $x$-value and a list of coefficients, and evaluates the polynomial defined by those coefficients. Here’s the function:

(defun poly (x a)
    (let ((result 0) (n (length a)))
         (dotimes (k n)
             (setq result (+ (* (nth k a) (expt x (- n k 1))) result)))
         result))

And here’s using it to evaluate the polynomial $2x^{3} - x^{2} + 5x - 10$ at $x = 3$:

(poly 3 '(2 -1 5 -10))

Then I thought how to turn each of those points into an ASCII-art graph.

The polt function uses two nested dolist loops iterating over a list of x-values and y-values, and then at each point, it has to decide domehow whether to plot a point (by returning “#” insread of the background character). The simplest solution is to only plot it if $y = f(x)$ and don’t otherwise, but this only works when lines cross exactly over the gridline.

After considering a number of other methods, I decided on the method that mattbatwings used in his Minecraft graphing calculator. This represents a function as 3D surface in $x$ and $y$, and then plotting all the points where the surface crosses the $x$-$y$ plane at $z=0$.

This function makes that decision. It takes the function $f$, the $x$ and $y$ coordinates, and $d$ which represents the distance between gird lines.

(defun zerocross (f x y d)
    (or
        (eq (< 0 (funcall f x y)) (> 0 (funcall f (- x d) y)))
        (eq (< 0 (funcall f x (- y d))) (> 0 (funcall f x y)))
        (eq (< 0 (funcall f x y)) (> 0 (funcall f (+ x d) y)))
        (eq (< 0 (funcall f x (+ y d))) (> 0 (funcall f x y)))))

If there is a sign change in the function close to the point, it returns t, otherwise it returns nil.

Now all that’s left to do is iterate over the provided ranges and call zerocross at each x- and y-value, and if there is no zero crossing, return the “background” characters.

axis returns a line character if it is on the axis, and dots for a grid at increments of 2.

(defun axis (x y)
    (if (and (= 0 x) (= 0 y)) "+"
        (if (= 0 x) "|"
            (if (= 0 y) "-"
                (if (and (= 0 (mod x 2)) (= 0 (mod y 2))) "." " ")))))

range is an emulation fo the Python range function, which returns a list of numbers from min up to max in increments of step.

(defun range (min max step)
    (let ((l nil) (c min))
         (loop
             (push c l)
             (setq c (+ c step))
             (when (>= c max) (return l)))))

plot then iterates over the entire x-y plane within the given range, and plots the function:

(defun plot (fx tx fy ty s fun)
    (with-output-to-string (out)
        (dolist (y (range fy ty s))
            (dolist (x (range fx tx s))
                (princ (if (zerocross fun x y s) "#" (axis x y)) out))
            (terpri out))))

If you’re interested in the whole code, here it is: plot.lisp

Here’s using it to plot the function $y^{3} + x^{2} - 10x - 70 = 0$:

(princ
    (plot
        -20 20 ; x-values
        -20 20 ; y-values
        1 ; step in each direction
        (lambda (x y) (+ (poly x '(1 -10 0)) (poly y '(1 0 0 -70))))))

This produces this neat graph:

                   |                    
 . . . . . . . . . | . . . . . . . . . .
                   |                    
 . . . . . . . . . | . . . . . . . . . .
                   |                    
 . . . . . . . . . | . . . . . . . . . .
                   |                    
 . . . . . . . . . | . . . . . . . . . .
                   |                    
 . . . . . . . . . | . . . . . . . . . .
                   |                    
 . . . . . . . . . | . . . . . . . . . .
                   |                    
 . . . . . . . . . | . . . . . . . . . .
         ###########                    
 . . .#################. . . . . . . . .
     ####          |####                
 . .## . . . . . . | . ##. . . . . . . .
    ##             |   ##               
----##-------------+---##---------------
    ##             |   ##               
 . ##. . . . . . . | . .## . . . . . . .
  ##               |     ##             
###. . . . . . . . | . . .###. . . . . .
##                 |       #####        
 . . . . . . . . . | . . . . ######. . .
                   |            ####### 
 . . . . . . . . . | . . . . . . . #####
                   |                   #
 . . . . . . . . . | . . . . . . . . . .
                   |                    
 . . . . . . . . . | . . . . . . . . . .
                   |                    
 . . . . . . . . . | . . . . . . . . . .
                   |                    
 . . . . . . . . . | . . . . . . . . . .
                   |                    
 . . . . . . . . . | . . . . . . . . . .
                   |                    
 . . . . . . . . . | . . . . . . . . . .

Pretty neat! An easy self-introduction to a programming language I though I’d never learn. Maybe I’ll take some time to learn more.

And here’s a bigger example: $x\sin\left(0.2\pi x\right)-y=0$:

(princ
    (plot
        -50 50 ; x-values
        -50 50 ; y-values
        1 ; step in each direction
        (lambda (x y) (- (* x (sin (* x pi 0.2))) y))))
                                                 |                                                  
 . . . . . . . . . . . . . . . . . . . . . . . . | . . . . . . . . . . . . . . . . . . . . . . . . .
                                                 |                                                  
 . . . . . . . . . . . . . . . . . . . . . . . . | . . . . . . . . . . . . . . . . . . . . . . . . .
                                                 |                                                  
 . . . . . . . . . . . . . . . . . . . . . . . . | . . . . . . . . . . . . . . . . . . . . . . . . .
                                                 |                                                  
 . . . . . . . . . . . . . . . . . . . . . . . . | . . . . . . . . . . . . . . . . . . . . . . . . .
      #                                          |                                          #       
 . . ### . . . . . . . . . . . . . . . . . . . . | . . . . . . . . . . . . . . . . . . . . ### . . .
     ####                                        |                                        ####      
 . . ####. . . . . . . . . . . . . . . . . . . . | . . . . . . . . . . . . . . . . . . . .#### . . .
     ####                                        |                                        ####      
 . . ####. . . . . . . . . . . . . . . . . . . . | . . . . . . . . . . . . . . . . . . . .#### . . .
     ####                                        |                                        ####      
 . . ####. . . . . . . . . . . . . . . . . . . . | . . . . . . . . . . . . . . . . . . . .#### . . .
     ####                                        |                                        ####      
 . . ####. . . .#. . . . . . . . . . . . . . . . | . . . . . . . . . . . . . . . .#. . . .#### . . .
     ####      ###                               |                               ###      ####      
 . . ####. . . ####. . . . . . . . . . . . . . . | . . . . . . . . . . . . . . .#### . . .#### . . .
     ####      ####                              |                              ####      ####     #
 . . ####. . . ####. . . . . . . . . . . . . . . | . . . . . . . . . . . . . . .#### . . .#### . . #
     ####      ####                              |                              ####      ####     #
 . . ####. . . ####. . . . . . . . . . . . . . . | . . . . . . . . . . . . . . .#### . . .#### . . #
    ## ##      ####                              |                              ####      ## ##    #
 . .## .## . . ####. . . . . . . . . . . . . . . | . . . . . . . . . . . . . . .#### . . ##. ##. . #
    ##  ##     ####                              |                              ####     ##  ##    #
 . .## .## . . ####. . . .#. . . . . . . . . . . | . . . . . . . . . . .#. . . .#### . . ##. ##. . #
    ##  ##     ####      ###                     |                     ###      ####     ##  ##    #
 . .## .## . . ####. . . ####. . . . . . . . . . | . . . . . . . . . .#### . . .#### . . ##. ##. . #
    ##  ##    ## ##      ####                    |                    ####      ## ##    ##  ##    #
 . .## .## . .## .## . . ####. . . . . . . . . . | . . . . . . . . . .#### . . ##. ##. . ##. ##. . #
    ##  ##    ##  ##     ####                    |                    ####     ##  ##    ##  ##    #
 . .## .## . .## .## . . ####. . . . . . . . . . | . . . . . . . . . .#### . . ##. ##. . ##. ##. . #
    ##  ##    ##  ##     ####                    |                    ####     ##  ##    ##  ##    #
 . .## .## . .## .## . .## ##. . . . . . . . . . | . . . . . . . . . .## ##. . ##. ##. . ##. ##. . #
    ##  ##    ##  ##    ## ##       #            |            #       ## ##    ##  ##    ##  ##    #
 . .## .## . .## .## . .## .## . . ### . . . . . | . . . . . ### . . ##. ##. . ##. ##. . ##. ##. . #
    ##  ##    ##  ##    ##  ##     ####          |          ####     ##  ##    ##  ##    ##  ##    #
 . .## .## . .## .## . .## .## . . ####. . . . . | . . . . .#### . . ##. ##. . ##. ##. . ##. ##. . #
    ##  ##    ##  ##    ##  ##     ####          |          ####     ##  ##    ##  ##    ##  ##    #
 . .## .## . .## .## . .## .## . .## ##. . . . . | . . . . .## ##. . ##. ##. . ##. ##. . ##. ##. . #
    ##  ##    ##  ##    ##  ##    ## ##          |          ## ##    ##  ##    ##  ##    ##  ##    #
 . .## .## . .## .## . .## .## . .## .## . . . . | . . . . ##. ##. . ##. ##. . ##. ##. . ##. ##. . #
    ##  ##    ##  ##    ##  ##    ##  ##         |         ##  ##    ##  ##    ##  ##    ##  ##    #
 . .## .## . .## .## . .## .## . .## .## . . . . | . . . . ##. ##. . ##. ##. . ##. ##. . ##. ##. . #
    ##  ##    ##  ##    ##  ##    ##  ##     ##  |  ##     ##  ##    ##  ##    ##  ##    ##  ##    #
 . .## .## . .## .## . .## .## . .## .## . .#### | ####. . ##. ##. . ##. ##. . ##. ##. . ##. ##. . #
    ##  ##    ##  ##    ##  ##    ##  ##    ## ##|## ##    ##  ##    ##  ##    ##  ##    ##  ##    #
#---##---##--##----##---##---##---##---##---##--###--##---##---##---##---##---##----##--##---##---##
#  ##    ##  ##    ##  ##    ##  ##    ##  ##    #    ##  ##    ##  ##    ##  ##    ##  ##    ##  ##
#. ##. . ##. ##. . ##. ##. . ##. ##. . ##. ##. . | . .## .## . .## .## . .## .## . .## .## . .## .##
#  ##    ##  ##    ##  ##    ##  ##    ##  ##    |    ##  ##    ##  ##    ##  ##    ##  ##    ##  ##
#. ##. . ##. ##. . ##. ##. . ##. ##. . ##.## . . | . . ##.## . .## .## . .## .## . .## .## . .## .##
#  ##    ##  ##    ##  ##    ##  ##    ## ##     |     ## ##    ##  ##    ##  ##    ##  ##    ##  ##
#. ##. . ##. ##. . ##. ##. . ##. ##. . .#### . . | . . ####. . .## .## . .## .## . .## .## . .## .##
#  ##    ##  ##    ##  ##    ##  ##     ###      |      ###     ##  ##    ##  ##    ##  ##    ##  ##
#. ##. . ##. ##. . ##. ##. . ##. ##. . . # . . . | . . . # . . .## .## . .## .## . .## .## . .## .##
#  ##    ##  ##    ##  ##    ##  ##              |              ##  ##    ##  ##    ##  ##    ##  ##
#. ##. . ##. ##. . ##. ##. . ##.## . . . . . . . | . . . . . . . ##.## . .## .## . .## .## . .## .##
#  ##    ##  ##    ##  ##    ## ##               |               ## ##    ##  ##    ##  ##    ##  ##
#. ##. . ##. ##. . ##. ##. . .#### . . . . . . . | . . . . . . . ####. . .## .## . .## .## . .## .##
#  ##    ##  ##    ##  ##     ####               |               ####     ##  ##    ##  ##    ##  ##
#. ##. . ##. ##. . ##. ##. . .#### . . . . . . . | . . . . . . . ####. . .## .## . .## .## . .## .##
#  ##    ##  ##    ##  ##     ####               |               ####     ##  ##    ##  ##    ##  ##
#. ##. . ##. ##. . ##.## . . .#### . . . . . . . | . . . . . . . ####. . . ##.## . .## .## . .## .##
#  ##    ##  ##    ## ##      ###                |                ###      ## ##    ##  ##    ##  ##
#. ##. . ##. ##. . .#### . . . # . . . . . . . . | . . . . . . . . # . . . ####. . .## .## . .## .##
#  ##    ##  ##     ####                         |                         ####     ##  ##    ##  ##
#. ##. . ##. ##. . .#### . . . . . . . . . . . . | . . . . . . . . . . . . ####. . .## .## . .## .##
#  ##    ##  ##     ####                         |                         ####     ##  ##    ##  ##
#. ##. . ##.## . . .#### . . . . . . . . . . . . | . . . . . . . . . . . . ####. . . ##.## . .## .##
#  ##     ####      ####                         |                         ####      ####     ##  ##
#. ##. . .#### . . .#### . . . . . . . . . . . . | . . . . . . . . . . . . ####. . . ####. . .## .##
#  ##     ####      ####                         |                         ####      ####     ##  ##
#. ##. . .#### . . .###. . . . . . . . . . . . . | . . . . . . . . . . . . .###. . . ####. . .## .##
#  ##     ####       #                           |                           #       ####     ##  ##
#.## . . .#### . . . . . . . . . . . . . . . . . | . . . . . . . . . . . . . . . . . ####. . . ##.##
####      ####                                   |                                   ####      #### 
#### . . .#### . . . . . . . . . . . . . . . . . | . . . . . . . . . . . . . . . . . ####. . . ####.
####      ####                                   |                                   ####      #### 
#### . . .#### . . . . . . . . . . . . . . . . . | . . . . . . . . . . . . . . . . . ####. . . ####.
####      ####                                   |                                   ####      #### 
#### . . .#### . . . . . . . . . . . . . . . . . | . . . . . . . . . . . . . . . . . ####. . . ####.
####      ####                                   |                                   ####      #### 
#### . . .###. . . . . . . . . . . . . . . . . . | . . . . . . . . . . . . . . . . . .###. . . ####.
####       #                                     |                                     #       #### 
#### . . . . . . . . . . . . . . . . . . . . . . | . . . . . . . . . . . . . . . . . . . . . . ####.
####                                             |                                             #### 
#### . . . . . . . . . . . . . . . . . . . . . . | . . . . . . . . . . . . . . . . . . . . . . ####.
####                                             |                                             #### 
#### . . . . . . . . . . . . . . . . . . . . . . | . . . . . . . . . . . . . . . . . . . . . . ####.
####                                             |                                             #### 
#### . . . . . . . . . . . . . . . . . . . . . . | . . . . . . . . . . . . . . . . . . . . . . ####.
###                                              |                                              ### 
 # . . . . . . . . . . . . . . . . . . . . . . . | . . . . . . . . . . . . . . . . . . . . . . . # .
                                                 |                                                  
 . . . . . . . . . . . . . . . . . . . . . . . . | . . . . . . . . . . . . . . . . . . . . . . . . .
                                                 |                                                  
 . . . . . . . . . . . . . . . . . . . . . . . . | . . . . . . . . . . . . . . . . . . . . . . . . .