//
// Simple demo created in response to https://stackoverflow.com/q/58313806/1553090
//
// Each line of input contains a single integer specifying target sample size,
// followed by any number of input samples
//
#include <cmath>
#include <iostream>
#include <numeric>
#include <sstream>
#include <string>
#include <vector>
// Uncomment this to output internal buffers during resampling
//#define INTERNAL_DBG
// Really dumb vector stream output
std::ostream& operator<<(std::ostream& s, const std::vector<int>& v)
{
for (int n : v) s << n << " ";
return s;
}
// Resamples times, preserving cumulative total
std::vector<int> resample_times(const std::vector<int>& times, int size)
{
// Handle case where no resampling is required
if (size == times.size())
return times;
// Calculate cumulative sum of times
std::vector<int> cumsum;
cumsum.reserve(times.size() + 1);
cumsum.push_back(0);
cumsum.insert(cumsum.end(), times.begin(), times.end());
std::partial_sum(cumsum.begin(), cumsum.end(), cumsum.begin());
#ifdef INTERNAL_DBG
std::cout << "Original times: " << times << std::endl;
std::cout << "Original sums: " << cumsum << std::endl;
#endif
// Resample cumulative sums
std::vector<int> resampled(size);
if (size == 1)
{
resampled[0] = cumsum.back();
}
else
{
for (int i = 0; i < size; ++i)
{
// Calculate index and interpolant in original array
double t = (double)i / (size-1) * times.size();
int pos = std::floor(t);
t -= pos;
// Lerp the value
resampled[i] = std::round(cumsum[pos] * (1.0-t) + cumsum[pos+1] * t);
}
}
#ifdef INTERNAL_DBG
std::cout << "Resampled sum: " << resampled << std::endl;
#endif
// Convert resampled sums back to deltas
std::adjacent_difference(resampled.begin(), resampled.end(), resampled.begin());
#ifdef INTERNAL_DBG
std::cout << "Resampled times: " << resampled << std::endl;
#endif
return resampled;
}
int main()
{
for(std::string line; std::getline(std::cin, line); )
{
std::istringstream input(line);
int newSize;
if (!(input >> newSize) || newSize <= 0)
{
std::cerr << "Invalid sample size" << std::endl;
continue;
}
std::vector<int> noisy;
for(int val; input >> val; ) noisy.push_back(val);
if (noisy.empty())
{
std::cerr << "Nothing to resample" << std::endl;
continue;
}
std::vector<int> resampled = resample_times(noisy, newSize);
std::cout << resampled << std::endl;
};
return 0;
}