8th September 2020
In an earlier post I proposed the challenge of writing the shortest Common Lisp function to sort a list of numbers into ascending order: Shortest sort answers.
I was recently experimenting with applying the same challenge to a quicksort. For example:
CL-USER > (quicksort '(3 1 4 1 5 9 2 6 5 3 5 8)) (1 1 2 3 3 4 5 5 5 6 8 9)
The solution can use any Common Lisp functions you want, apart, of course, from sort or stable-sort.
To get the score, count the non-nil atoms in the function definition(s) using count-atoms:
(defun count-atoms (form) (typecase form (null 0) (atom 1) (cons (+ (count-atoms (car form)) (count-atoms (cdr form))))))
Here's the best solution that I've found, with a count of 28 non-nil atoms:
(defun quicksort (lis) (when lis (destructuring-bind (p . r) lis (flet ((less (x) (< x p))) (append (quicksort (remove-if-not #'less r)) (list p) (quicksort (remove-if #'less r)))))))
It works as follows:
- Choose a 'pivot' element p in the list to be sorted and remove it from the list to give a list r. For simplicity this function chooses the first item in the list as the pivot.
- Split r into two lists: a, containing all the elements less than p, and b, containing all the elements greater than p.
- Recursively call quicksort on a and b.
- The result is got by appending a, (list p), and b.
Can you improve on this solution?
blog comments powered by Disqus