grade_report.scala in Scala
Per-student averages, letter grades and a class summary from an inline roster.
// A per-student grade report from an inline roster.
case class Student(name: String, scores: List[Int])
val roster: List[Student] = List(
Student("Ada Byron", List(92, 88, 100, 95)),
Student("Grace Hopper", List(78, 84, 80, 91)),
Student("Alan Turing", List(65, 72, 58, 70)),
Student("Katherine J.", List(99, 97, 94, 100)),
Student("Edsger D.", List(55, 61, 49, 64)),
)
def average(scores: List[Int]): Double =
if scores.isEmpty then 0.0 else scores.sum.toDouble / scores.size
// Guards turn one match into a ladder of thresholds, read top down,
// so the first case that fits wins.
def letter(avg: Double): String = avg match
case a if a >= 90 => "A"
case a if a >= 80 => "B"
case a if a >= 70 => "C"
case a if a >= 60 => "D"
case _ => "F"
@main def gradeReport(): Unit =
val graded = roster.map(s => (s, average(s.scores)))
// Best first, so the ranking is visible without reading averages.
val ranked = graded.sortBy((_, avg) => -avg)
println(f"${"student"}%-14s${"best"}%6s${"worst"}%6s${"avg"}%7s${"grade"}%7s")
println("-" * 40)
for (student, avg) <- ranked do
val best = student.scores.max
val worst = student.scores.min
println(f"${student.name}%-14s$best%6d$worst%6d$avg%7.1f${letter(avg)}%7s")
val classAvg = graded.map((_, avg) => avg).sum / graded.size
val passing = graded.count((_, avg) => avg >= 60)
println("-" * 40)
println(f"class average $classAvg%.1f (${letter(classAvg)})")
println(s"$passing of ${roster.size} students passing")
How it works
averagedividesscores.sum.toDoubleby the number of scores.letterreads as a ladder of thresholds through guards such ascase a if a >= 90.sortBy((_, avg) => -avg)puts the best first, and${student.name}%-14spads each name to a fixed column.
Keywords and builtins used here
DoubleIntListStringStudentUnitaveragecaseclassdefdoelseforgradeReportiflettermatchthenval
The run, in numbers
- Lines
- 41
- Characters to type
- 1469
- Tokens
- 388
- Three-star pace
- 75 tpm
At the three-star pace of 75 tokens a minute, this run takes about 310 seconds.
Step 2 of 3 in Encore, step 26 of 27 in Language basics.