I would really appreciate it if someone could review my LISP code. I was attempting to write a quicksort implementation. Additionally, I generated my list dynamically and wrote a couple of tests. Of course, I realize that the tests are not complete, but I decided to stop where I was and see if I could get some feedback. Thanks in advance for any help you can offer!
(defun categorize_list(pivot thelist less more)
(let ((comparee (car thelist)) (therest (cdr thelist)))
(if (null thelist)
(list less more)
(if (< comparee pivot)
(categorize_list pivot therest (append less (list comparee)) more)
(categorize_list pivot therest less (append more (list comparee)))
)
)
)
)
(defun quicksort(thelist)
(if (null thelist)
()
(let (
(pivot (car thelist))
(therest (cdr thelist))
)
(let ((categorized_list (categorize_list pivot therest () ())))
(append (quicksort (nth 0 categorized_list)) (list pivot) (quicksort (nth 1 categorized_list)))
)
)
)
)
(defun make_list(thelist remaininglength)
(if (eq remaininglength 0)
thelist
(make_list (append (list (random 25)) thelist) (- remaininglength 1))
)
)
(defun should_be_least_to_greatest(thelist)
(if (< (length thelist) 2)
nil
(if (<= (nth 0 thelist) (nth 1 thelist))
(should_be_least_to_greatest (cdr thelist))
(error "Out of order: ~d !< ~d ~%" (nth 0 thelist) (nth 1 thelist))
)
)
)
(defun test_should_become_in_order(thelist)
(let ((sortedList (quicksort thelist)))
(format t "IN: ~a ~% SD: ~a ~% Testing sort.~%" thelist sortedList)
(should_be_least_to_greatest sortedList)
)
)
(defun test_should_maintain_length(thelist)
(if (not (eql (length thelist) (length (quicksort thelist))))
(error "The sorted list is a different length than the original list! ~%")
)
)
(let ((thelist (make_list () 10)))
(test_should_become_in_order thelist)
(test_should_maintain_length thelist)
)
Thank you very much for your constructive criticism! I have made a revision based on one of the commenters suggestions. If you have any further advice based on this new version, I would really appreciate your help.
(defun categorize-list(pivot the-list less more)
(let ((comparee (car the-list)) (the-rest (cdr the-list)))
(if (null the-list)
(list less more)
(if (< comparee pivot)
(categorize-list pivot the-rest (append less (list comparee)) more)
(categorize-list pivot the-rest less (append more (list comparee)))))))
(defun quicksort(the-list)
(unless (null the-list)
(let ((pivot (car the-list)) (the-rest (cdr the-list)))
(let ((categorized-list (categorize-list pivot the-rest () ())))
(append (quicksort (nth 0 categorized-list)) (list pivot) (quicksort (nth 1 categorized-list)))))))
(defun generate-random-list(length)
(let ((the-list ()))
(loop for l from 1 to length do (setq the-list (append the-list (list (random 25))))) the-list))
(defun should-be-least-to-greatest(the-list)
(loop for l from 0 to (- (length the-list) 2) do
(unless (<= (nth l the-list) (nth (+ l 1) the-list)) (error "Out of order: ~d < ~d ~%" (nth l the-list) (nth (+ l 1) the-list)))))
(defun test-should-become-in-order(the-list)
(let ((sorted-list (quicksort the-list)))
(format t "IN: ~a ~% SD: ~a ~% Testing sort.~%" the-list sorted-list)
(should-be-least-to-greatest sorted-list)))
(defun test-should-maintain-length(the-list)
(unless (= (length the-list) (length (quicksort the-list))) (error "The sorted list is a different length than the original list! ~%")))
(let ((the-list (generate-random-list 10))) (test-should-become-in-order the-list) (test-should-maintain-length the-list))
Ken - thank you very much for continuing to help me improve this code. It is evident that you are quite experienced in this area and I'm sure you're very busy, so it means a lot to me! I adopted your suggestions with respect to loop and read up on the syntax of LET* so I hope that I've made some improvements in that area. I also got rid of nth in favor of using first and second throughout the code. One area which I'm still trying to improve on is managing the width of the code for readability. In this new revision, I have spaced arguments for a particularly long function call onto separate lines to try and make it more readable, but I'm not sure if it is ok because the formatting seems a bit odd. What do you think? Also, if you have any further suggestions, I am all ears. Again, thanks so much! I appreciate your help.
(defun categorize-list (pivot the-list less more)
(let ((comparee (car the-list)) (the-rest (cdr the-list)))
(if (null the-list)
(list less more)
(if (< comparee pivot)
(categorize-list pivot
the-rest
(append less (list comparee))
more)
(categorize-list pivot
the-rest
less
(append more (list comparee)))))))
(defun quicksort (the-list)
(unless (null the-list)
(let (categorized-list (pivot (car the-list)) (the-rest (cdr the-list)))
(setq categorized-list (categorize-list pivot the-rest () ()))
(append (quicksort (first categorized-list))
(list pivot)
(quicksort (second categorized-list))))))
(defun generate-random-list (length)
(loop for l from 1 to length collect (random 25)))
(defun should-be-least-to-greatest (the-list)
(loop for p on the-list while (second p)
when (< (second p) (first p))
do (error "Out of order: ~d < ~d ~%" (first p) (second p))))
(defun test-should-become-in-order (the-list)
(let ((sorted-list (quicksort the-list)))
(format t "IN: ~a ~% SD: ~a ~% Testing sort.~%" the-list sorted-list)
(should-be-least-to-greatest sorted-list)))
(defun test-should-maintain-length (the-list)
(unless (= (length the-list) (length (quicksort the-list)))
(error "The sorted list is a different length than the original list! ~%")))
(let ((the-list (generate-random-list 10)))
(test-should-become-in-order the-list)
(test-should-maintain-length the-list))