long readTemperature() {
  return random(-20, 30);
}


unsigned long pMillis() {
  unsigned long const now {millis()};
  return now ? now : 1;  // Timestamp 0 is reserved.
}

template <size_t n> size_t findMinimum(unsigned long const (& measurements)[n], unsigned long const timespan) {
  unsigned long const now {pMillis()};
  for (size_t i {0}; i < n; ++i) {
    if (measurements[i] and now - measurements[i] < timespan) {
      return i;
    }
  }
  return n;  // Should be unreachable.
}

template <size_t n> size_t findMaximum(unsigned long const (& measurements)[n], unsigned long const timespan) {
  unsigned long const now {pMillis()};
  for (size_t i {n}; i--;) {
    if (measurements[i] and now - measurements[i] < timespan) {
      return i;
    }
  }
  return n;  // Should be unreachable.
}


void setup() {
  Serial.begin(9600);
}

void loop() {
  static unsigned long measurements[50] {};
  long const offset {20};  // Temperature is between -20°C and 30°C.

  long const temperature {readTemperature()};
  measurements[temperature + offset] = pMillis();

  Serial.print("Current: ");
  Serial.print(temperature);

  Serial.print(",  Minima (3s, 6s): ");
  Serial.print(findMinimum(measurements, 3000) - offset);    // Minimum over the last 3s.
  Serial.print(", ");
  Serial.print(findMinimum(measurements, 6000) - offset);    // Minimum over the last 6s.

  Serial.print(",  Maxima (3s, 6s): ");
  Serial.print(findMaximum(measurements, 3000) - offset);    // Maximum over the last 3s.
  Serial.print(", ");
  Serial.println(findMaximum(measurements, 6000) - offset);  // Maximum over the last 6s.

  delay(1000);
}