// Ten days of readings, and three questions answered from the latest day
// backwards: recent moving averages, recent day-over-day changes, and every
// third day counted back from today.
//
// nikaia run
// moving average over 3 days, latest first:
// 25
// …
// peak: day 9, 28
// every third day, from today back: 28 22 17 12
//
// Shows: sequence pipelines (`windows`, `map`, `zip`, `skip`, `step_by`) walked
// from the back with `rev`, and a range used as a value.
//
// A package: `nikaia run` in this directory runs it, and `nikaia test` checks
// what it prints against `tests/` (ADR-269 D13).
fn main() {
let readings = [12, 14, 13, 17, 19, 18, 22, 25, 24, 28]
let n = 3
println(f"moving average over {n} days, latest first:")
let averages = readings.windows(n).map(fn(w) {
let mut total = 0
for x in w {
total += x
}
total / n
})
// `rev` walks the pipeline from its back end; nothing is collected or
// copied on the way. `windows` hands out views of the list, and a `map`
// walked from the back is its input walked from the back. Not every
// sequence has a back end: `io::lines().rev()` is a compile error.
for average in averages.rev().take(3) {
println(f" {average}")
}
println("day over day, latest first:")
let changes = readings.iter().zip(readings.iter().skip(1))
// `zip` and `skip` can be walked from the back only when the length of
// what goes in is known. A list's is; after a `filter` it would not be.
for (before, after) in changes.rev().take(3) {
println(f" {before} -> {after}: {after - before}")
}
// A range is a value: `days` is walked twice, here and below. A produced
// sequence such as `averages` can be walked only once.
let days = 0..<readings.len()
let mut peak = 0
for day in days {
if readings[day] > readings[peak] {
peak = day
}
}
println(f"peak: day {peak}, {readings[peak]}")
print("every third day, from today back:")
for day in days.step_by(3).rev() {
print(f" {readings[day]}")
}
println("")
}
The file itself · all the examples