typestar

temp_stats.scala in Scala

One week of high temperatures as a table of stats and a bar chart.

// Daily high temperatures for one week, summarized as a bar chart.

val week: List[(String, Int)] = List(
  ("Mon", 61), ("Tue", 68), ("Wed", 74),
  ("Thu", 71), ("Fri", 59), ("Sat", 55), ("Sun", 66),
)

val highs: List[Int] = week.map((_, temp) => temp)
val mean: Double = highs.sum.toDouble / highs.size

// Measuring each bar from the coldest day spends the width on the
// differences; the coldest day itself keeps a single mark.
def bar(temp: Int, floor: Int): String = "#" * (temp - floor + 1)

// Each day is marked against the week's mean, which is what makes
// the table say something the raw numbers do not.
def mark(temp: Int): String =
  if temp > mean then "above"
  else if temp < mean then "below"
  else "even"

@main def tempStats(): Unit =
  val coldest = highs.min
  val warmest = highs.max
  val (coldDay, _) = week.minBy((_, temp) => temp)
  val (warmDay, _) = week.maxBy((_, temp) => temp)

  println(f"${"day"}%-5s${"high"}%6s  ${"vs mean"}%-8s${"chart"}%s")
  println("-" * 40)
  for (day, temp) <- week do
    println(f"$day%-5s$temp%6d  ${mark(temp)}%-8s${bar(temp, coldest)}%s")
  println("-" * 40)

  println(f"mean   $mean%6.1f")
  println(f"range  ${warmest - coldest}%6d degrees")
  println(s"coldest $coldDay at $coldest, warmest $warmDay at $warmest")

How it works

  1. highs.sum.toDouble / highs.size gives the mean that every row is judged against.
  2. mark labels a day above or below it, and "#" * (temp - floor + 1) draws the bar from the coldest day up.
  3. week.minBy((_, temp) => temp) and its maxBy twin name the days in the closing summary.

Keywords and builtins used here

The run, in numbers

Lines
36
Characters to type
1250
Tokens
309
Three-star pace
80 tpm

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

Type this snippet

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

← Previous