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
reducewith#'minand#'maxbounds the week;meanaverages the same list.barscales each reading betweenlowandhighand builds marks withmake-string.- Each row is tagged
"above"or"below"againstavg, and~7,1fkeeps one decimal place.
Keywords and builtins used here
defparameterdefundolistfirstformatiflambdalengthletmapcarmaxminreduceroundsecondvalues
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.
Step 3 of 3 in Encore, step 27 of 27 in Language basics.