136. Generic Moving Average Filter

#include <iostream>
#include <iomanip>

template <typename T, int WindowSize>
class MovingAverage {
private:
    T buffer[WindowSize];
    int count; // Total valid samples added so far (capped at WindowSize)
    int index; // Where to write the *next* sample

public:
    MovingAverage() : count(0), index(0) {}

    T addSample(T sample) {
        // Overwrite oldest sample
        buffer[index] = sample;

        // Move index circularly
        index = (index + 1) % WindowSize;

        // Track how many items we have valid
        if (count < WindowSize) {
            count++;
        }

        // Calculate Average
        T sum = 0;
        for (int i = 0; i < count; ++i) {
            sum += buffer[i];
        }
        return sum / count;
    }
};

int main() {
    MovingAverage<float, 4> filter;

    int N;
    if (!(std::cin >> N)) return 0;

    for (int i = 0; i < N; ++i) {
        float sample;
        std::cin >> sample;

        float avg = filter.addSample(sample);
        
        std::cout << "Avg: " << std::fixed << std::setprecision(2) << avg << std::endl;
    }
    return 0;
}

Explanation & Logic Summary:

  • Templates for Signal Processing: This problem demonstrates creating a generic component that processes data streams. By making WindowSize a template parameter, the compiler creates a fixed-size array buffer[4], avoiding the runtime overhead of pointers and heap allocation (malloc).
  • Circular Buffer Logic: The index wraps around using modulo (% WindowSize). This overwrites the oldest data naturally.
  • Partial Window Handling: The logic if (count < WindowSize) count++; handles the startup transient where the buffer isn't full yet (e.g., dividing by 1, then 2, then 3).

Firmware Relevance & Real-World Context:

  • ADC Smoothing: Virtually all analog sensors (temperature, battery voltage) require averaging to remove electrical noise.
  • Compile-Time Optimization: Since WindowSize is known at compile time, the compiler can unroll the summation loop or use SIMD instructions on advanced DSP chips.
  • Zero Overhead: This implementation is as fast as a hand-written specific version for float and size 4.

 

 

 

 

 

Loading...

Input

5 10.0 20.0 30.0 40.0 50.0

Expected Output

Avg: 10.00 Avg: 15.00 Avg: 20.00 Avg: 25.00 Avg: 35.00