;;;
;;; find path from start to finish which goes through
;;; each node only once
;;;
(defparameter start '(a f l k s))
(defparameter a '(f b h d))
(defparameter b '(a l m g))
(defparameter c '(d o i g))
(defparameter d '(a h c o j))
(defparameter e '(k p s))
(defparameter f '(a l))
(defparameter g '(b c h m n))
(defparameter h '(a d g))
(defparameter i '(c r n finish))
(defparameter j '(d o))
(defparameter k '(e))
(defparameter l '(f b p))
(defparameter m '(b g n p))
(defparameter n '(g i m u finish))
(defparameter o '(j d c r finish))
(defparameter p '(l m e v))
(defparameter q '(v p m n u))
(defparameter r '(i o))
(defparameter s '(e v finish))
(defparameter v '(s p u))
(defparameter u '(q v n finish))
(defparameter finish '())

;;;
;;; states is a list of partial paths.
;;; the initial state would be ((start)).
;;; states after visiting start will be
;;; ((a start) (f start) (l start) (k start) (s start))
;;; and so on.
;;;
(defun walk-path (to states)
  (if (null states)                              ; the search is exhausted
      nil                                        ;   return no solution
      (let* ((path (first states))               ; otherwise, get the next partial path
             (node (first path)))                ;  and the last node on the path (path is in reverse order)
        (if (and (equal node to)                 ; if this is the terminal node
                 (equal (length path) 23))       ;   and all nodes have been visited
            (reverse path)                       ;   return the solution
                                                 ; otherwise, create a list of unvisited nodes
                                                 ;  from node, add them to the path, and
                                                 ;  the state space to be searched
            (let ((next-nodes (set-difference (symbol-value node) path)))
              (walk-path to
                        (append (rest states)
                                (mapcar (lambda (node) (cons node path)) next-nodes))))))))

;;;
;;; solution is:
;;;   (path 'start 'finish)
;;;
(defun path (from to)
  (walk-path to (list (list from))))