typestar

grade_report.lisp in Lisp

Turns a list of students and test scores into per-student grades and a class summary.

;; grade_report.lisp: student averages, letter grades, and a class summary.

(defparameter *students*
  '(("Ada" 92 88 95)
    ("Grace" 78 85 80)
    ("Alan" 65 72 70)
    ("Edsger" 88 91 84)
    ("Barbara" 55 61 58)))

(defun average (scores)
  (/ (reduce #'+ scores) (float (length scores))))

(defun letter-grade (score)
  (cond ((>= score 90) "A")
        ((>= score 80) "B")
        ((>= score 70) "C")
        ((>= score 60) "D")
        (t "F")))

(defun report-row (record)
  (let* ((name (first record))
         (scores (rest record))
         (mean (average scores)))
    (format t "~10a ~{~5d~} ~9,2f ~a~%"
            name scores mean (letter-grade mean))))

(format t "~10a ~15a ~9a ~a~%" "student" "scores" "average" "grade")
(dolist (record *students*)
  (report-row record))

(let* ((means (mapcar (lambda (record) (average (rest record))) *students*))
       (class-mean (/ (reduce #'+ means) (length means)))
       (passing (count-if (lambda (mean) (>= mean 70)) means)))
  (format t "~%class average ~,2f over ~d student~:p~%"
          class-mean (length means))
  (format t "passing at 70 or better: ~d of ~d~%" passing (length means))
  (format t "highest average: ~,2f~%" (reduce #'max means)))

How it works

  1. average divides by (float (length scores)) so the result is not a ratio.
  2. letter-grade walks a cond from 90 down to the fallback t clause.
  3. ~10a ~{~5d~} ~9,2f lines the columns up; count-if counts averages at 70 or better.

Keywords and builtins used here

The run, in numbers

Lines
37
Characters to type
1097
Tokens
262
Three-star pace
75 tpm

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

Type this snippet

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

← Previous Next →