fork download
  1. //
  2. // Simple demo created in response to https://stackoverflow.com/q/58313806/1553090
  3. //
  4. // Each line of input contains a single integer specifying target sample size,
  5. // followed by any number of input samples
  6. //
  7. #include <cmath>
  8. #include <iostream>
  9. #include <numeric>
  10. #include <sstream>
  11. #include <string>
  12. #include <vector>
  13.  
  14. // Uncomment this to output internal buffers during resampling
  15. //#define INTERNAL_DBG
  16.  
  17. // Really dumb vector stream output
  18. std::ostream& operator<<(std::ostream& s, const std::vector<int>& v)
  19. {
  20. for (int n : v) s << n << " ";
  21. return s;
  22. }
  23.  
  24.  
  25. // Resamples times, preserving cumulative total
  26. std::vector<int> resample_times(const std::vector<int>& times, int size)
  27. {
  28. // Handle case where no resampling is required
  29. if (size == times.size())
  30. return times;
  31.  
  32. // Calculate cumulative sum of times
  33. std::vector<int> cumsum;
  34. cumsum.reserve(times.size() + 1);
  35. cumsum.push_back(0);
  36. cumsum.insert(cumsum.end(), times.begin(), times.end());
  37. std::partial_sum(cumsum.begin(), cumsum.end(), cumsum.begin());
  38.  
  39. #ifdef INTERNAL_DBG
  40. std::cout << "Original times: " << times << std::endl;
  41. std::cout << "Original sums: " << cumsum << std::endl;
  42. #endif
  43.  
  44. // Resample cumulative sums
  45. std::vector<int> resampled(size);
  46.  
  47. if (size == 1)
  48. {
  49. resampled[0] = cumsum.back();
  50. }
  51. else
  52. {
  53. for (int i = 0; i < size; ++i)
  54. {
  55. // Calculate index and interpolant in original array
  56. double t = (double)i / (size-1) * times.size();
  57. int pos = std::floor(t);
  58. t -= pos;
  59.  
  60. // Lerp the value
  61. resampled[i] = std::round(cumsum[pos] * (1.0-t) + cumsum[pos+1] * t);
  62. }
  63. }
  64.  
  65. #ifdef INTERNAL_DBG
  66. std::cout << "Resampled sum: " << resampled << std::endl;
  67. #endif
  68.  
  69. // Convert resampled sums back to deltas
  70. std::adjacent_difference(resampled.begin(), resampled.end(), resampled.begin());
  71.  
  72. #ifdef INTERNAL_DBG
  73. std::cout << "Resampled times: " << resampled << std::endl;
  74. #endif
  75.  
  76. return resampled;
  77. }
  78.  
  79.  
  80. int main()
  81. {
  82. for(std::string line; std::getline(std::cin, line); )
  83. {
  84. std::istringstream input(line);
  85. int newSize;
  86.  
  87. if (!(input >> newSize) || newSize <= 0)
  88. {
  89. std::cerr << "Invalid sample size" << std::endl;
  90. continue;
  91. }
  92.  
  93. std::vector<int> noisy;
  94. for(int val; input >> val; ) noisy.push_back(val);
  95. if (noisy.empty())
  96. {
  97. std::cerr << "Nothing to resample" << std::endl;
  98. continue;
  99. }
  100.  
  101. std::vector<int> resampled = resample_times(noisy, newSize);
  102. std::cout << resampled << std::endl;
  103. };
  104.  
  105. return 0;
  106. }
Success #stdin #stdout 0s 4564KB
stdin
5 0 5 12 2 50 100 20 3 9 33
10 0 5 12 2 50 100 20 3 9 33
15 0 5 12 2 50 100 20 3 9 33
4 0 5 12 2 50
5 0 5 12 2 50
10 0 5 12 2 50
11 0 5 12 2 50
12 0 5 12 2 50
1 0 10 100 420
stdout
0 11 58 122 43 
0 5 12 2 50 100 20 3 9 33 
0 0 2 5 8 3 15 36 71 38 11 3 5 13 24 
0 3 15 51 
0 5 12 2 50 
0 0 1 2 5 6 4 1 22 28 
0 0 0 3 2 6 6 1 1 25 25 
0 0 0 2 2 4 6 3 1 6 22 23 
530