typestar

temp_stats.lisp in Lisp

Reports a week of daily high temperatures with min, max, mean, and a text bar chart.

;; temp_stats.lisp: a week of daily high temperatures, summarized.

(defparameter *readings*
  '(("Mon" 61.5) ("Tue" 64.0) ("Wed" 70.2) ("Thu" 72.8)
    ("Fri" 68.4) ("Sat" 59.9) ("Sun" 63.1)))

(defun highs (readings)
  (mapcar #'second readings))

(defun mean (values)
  (/ (reduce #'+ values) (length values)))

(defun bar (value low high width)
  "Return a bar of at most WIDTH marks scaling VALUE between LOW and HIGH."
  (let ((span (- high low)))
    (make-string (max 1 (round (* width (/ (- value low) span))))
                 :initial-element #\#)))

(let* ((values (highs *readings*))
       (low (reduce #'min values))
       (high (reduce #'max values))
       (avg (mean values))
       (warm (count-if (lambda (value) (>= value avg)) values)))
  (format t "daily highs in degrees Fahrenheit~%~%")
  (format t "~5a ~7a ~7a ~a~%" "day" "high" "vs avg" "trend")
  (dolist (reading *readings*)
    (let ((day (first reading))
          (value (second reading)))
      (format t "~5a ~7,1f ~7a ~a~%"
              day value
              (if (>= value avg) "above" "below")
              (bar value low high 20))))
  (format t "~%low ~,1f  high ~,1f  mean ~,1f  spread ~,1f~%"
          low high avg (- high low))
  (format t "~d of ~d day~:p at or above the mean~%"
          warm (length values)))

How it works

  1. reduce with #'min and #'max bounds the week; mean averages the same list.
  2. bar scales each reading between low and high and builds marks with make-string.
  3. Each row is tagged "above" or "below" against avg, and ~7,1f keeps one decimal place.

Keywords and builtins used here

The run, in numbers

Lines
36
Characters to type
1155
Tokens
260
Three-star pace
80 tpm

At the three-star pace of 80 tokens a minute, this run takes about 195 seconds.

Type this snippet

Step 3 of 3 in Encore, step 27 of 27 in Language basics.

← Previous