This was my first attempt at writing a program in LISP. Can anyone give any guides as to how it could be improved? The multiple loops in best-pattern seem awkward (I'd normally do that in just one loop but there doesn't seem to be a way of doing that with LOOP, although I'm told there's an iterate extension that can do it), as does the way of calculating alternatives..
(defparameter *rows* (list (list :c :ds :fs :a) (list :cs :e :g :as) (list :d :f :gs :b)))
(defun row-for-note (note)
(position-if (lambda (row) (find note row)) *rows*)
)
(defun rows-for-notelist (notelist)
(mapcar #'row-for-note notelist)
)
(defun possible-alternates (rowlist)
(let ((alternatives '(()))) ;; Lots of irritating silly parentheses
(when (> (length rowlist) 1)
(setq alternatives (possible-alternates (cdr rowlist)))
)
(case (car rowlist)
((0) (mapcar (lambda (x) (append '(0) x)) alternatives))
((1) (append (mapcar (lambda (x) (append '(1) x)) alternatives)
(mapcar (lambda (x) (append '(-2) x)) alternatives)))
((2) (append (mapcar (lambda (x) (append '(2) x)) alternatives)
(mapcar (lambda (x) (append '(-1) x)) alternatives)))
)
)
)
(defun count-jumps (rowlist)
(loop for (a b) on rowlist while b counting (> (abs (- a b)) 1))
)
(defun best-pattern (notelist)
(let ((minval (loop for x in (possible-alternates (rows-for-notelist notelist)) minimize (count-jumps x))))
(loop for x in (possible-alternates (rows-for-notelist notelist)) when (= (count-jumps x) minval) collect x))
)
(If you're wondering what the program does, it tries to calculate the "most efficient" series of rows to use to play a melody on 5-row Bayan Accordion.)