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
highs.sum.toDouble / highs.sizegives the mean that every row is judged against.marklabels a day above or below it, and"#" * (temp - floor + 1)draws the bar from the coldest day up.week.minBy((_, temp) => temp)and its maxBy twin name the days in the closing summary.
Keywords and builtins used here
DoubleIntListStringUnitbardefdoelseforifmarktempStatsthenval
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.
Step 3 of 3 in Encore, step 27 of 27 in Language basics.