grade_report.clj in Clojure
Averages three test scores per student, assigns a letter grade, and closes with a class summary.
;; Term grade report for one small section.
(def roster
[{:student "Alvarez" :scores [88 92 79]}
{:student "Byrne" :scores [71 65 74]}
{:student "Chao" :scores [95 98 91]}
{:student "Dubois" :scores [59 66 62]}
{:student "Egan" :scores [82 85 80]}
{:student "Farkas" :scores [48 55 51]}])
;; Dividing by a double keeps the result out of ratio arithmetic.
(defn average [xs]
(if (seq xs)
(/ (reduce + xs) (double (count xs)))
0.0))
;; cond tries its test/result pairs in order and stops at the first
;; true test, so each band only needs its lower bound.
(defn letter [avg]
(cond
(>= avg 90) "A"
(>= avg 80) "B"
(>= avg 70) "C"
(>= avg 60) "D"
:else "F"))
;; for is a comprehension, not a loop: it returns a new sequence.
(def graded
(for [{:keys [student scores]} roster
:let [avg (average scores)]]
{:student student :avg avg :grade (letter avg)}))
(println (format "%-10s %6s %5s" "STUDENT" "AVG" "GRADE"))
(println (apply str (repeat 23 "-")))
(doseq [{:keys [student avg grade]} (sort-by :student graded)]
(println (format "%-10s %6.1f %5s" student avg grade)))
(println (apply str (repeat 23 "-")))
(println (format "%-10s %6.1f" "CLASS" (average (map :avg graded))))
(println (format "%-10s %6d" "PASSING"
(count (remove #(= "F" (:grade %)) graded))))
How it works
(/ (reduce + xs) (double (count xs)))averages the scores, and thedoublecall keeps the result out of ratio arithmetic.letteruses acondrunning from(>= avg 90)down to:else, so each band states only its lower bound.(for [{:keys [student scores]} rosterdestructures every entry, and:let [avg (average scores)]computes the average once per student.
Keywords and builtins used here
applyaveragecondcountdefdefndoseqdoubleforformatiflettermapprintlnreduceremoverepeatseqstr
The run, in numbers
- Lines
- 39
- Characters to type
- 1277
- Tokens
- 275
- Three-star pace
- 75 tpm
At the three-star pace of 75 tokens a minute, this run takes about 220 seconds.
Step 2 of 3 in Encore, step 26 of 27 in Language basics.