Last active
June 22, 2021 14:02
-
-
Save svetlyak40wt/56a29b6533fbe3332728c546776da381 to your computer and use it in GitHub Desktop.
Common Lisp function to put data into buckets and print historgram
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; License BSD | |
(defpackage #:histogram | |
(:use #:cl) | |
(:export | |
#:print-histogram)) | |
(in-package histogram) | |
(defun min-value (values) | |
"Ищет минимальное по любому количеству элементов." | |
(- (loop for value in values | |
minimizing value) | |
;; Чуть чуть сместим концы границы, чтобы точно всё влезло | |
0.01)) | |
(defun max-value (values) | |
"Ищет максимальное по любому количеству элементов." | |
(+ (loop for value in values | |
maximizing value) | |
0.01)) | |
(defun print-histogram (data &key | |
(num-buckets 40) | |
(width 40) ;; number of symbols in a chart for the largest bucket | |
min-value | |
max-value | |
(as-percents t) | |
(stream *standard-output*)) | |
(let* ((min-value (or min-value | |
(min-value (coerce data 'list)))) | |
(max-value (or max-value | |
(max-value (coerce data 'list)))) | |
(step (/ (- max-value min-value) | |
(- num-buckets 1))) | |
(buckets (make-array num-buckets :initial-element 0))) | |
(flet ((add-value-to-the-bucket (value) | |
"Finds a bucket for the value and increments it's counter." | |
(when (<= min-value value max-value) | |
(let ((index (floor (/ (- value min-value) | |
step)))) | |
(incf (aref buckets index))))) | |
(make-bar (number width label) | |
"Prints a line filled with = symbol with the label at the end." | |
(if (zerop width) | |
(format stream "~10<~,2F~>:~%" | |
number) | |
(format stream "~10<~,2F~>: ~a ~a~%" | |
number | |
(coerce (make-array width :initial-element #\=) | |
'string) | |
(unless (zerop width) | |
label))))) | |
;; Now add all data points to their buckets | |
(mapc #'add-value-to-the-bucket | |
(coerce data 'list)) | |
;; And print bucket values as a ASCII chart | |
(let ((max-bucket-size | |
(apply #'max (coerce buckets 'list)))) | |
(loop for value across buckets | |
for number from min-value to max-value by step | |
do (make-bar number | |
(floor (* (/ value max-bucket-size) | |
width)) | |
(if as-percents | |
(format nil "~5,2f%" (* (/ value (length data)) | |
100)) | |
value))))))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment