(defun report (listsOfNums &keys (width 50) (label 30)) "listOfNums ==> ((label1 num num num) (label2 num num num))" (let* ((cdrs (maplist #'cdr listOfNums)) (nums (sort (flatten cdrs) #'<)) (min (first nums)) (max (first (last nums))) (norm #'(lambda (n) (round (* 100 (/ (- n min) (- min)))))) (reports (mapcar #(lambda (list) (report1 width label (first list) (sort (rest list) #'<) norm))))) reports)) (defun report1 (width string label nums norm) (let ((n (length nums)) (p100 (first (last nums))) (p90 (nth (floor (* n 0.9)) nums)) (p70 (nth (floor (* n 0.7)) nums)) (p50 (nth (floor (* n 0.5)) nums)) (p30 (nth (floor (* n 0.3)) nums)) (p10 (nth (floor (* n 0.1)) nums)) (fmt (format nil "~~~as ~~a.2f ~~a.2f ~~a.2f ~~a.2f ~~a.2f ~~a.2f ~~a.2f" string width width width width width)) (p0 (first nums)) (our (make-array `(,(+ 1 width)) :initial-element " "))) (setf (aref out 1) (format nil fmt label p0 p10 p30 p50 p70 p90 p100))