Home > front end >  Sum the elements from a vector using a nested for loop
Sum the elements from a vector using a nested for loop

Time:12-22

I'm trying to sum the values of a vector but I have a problem with that.

The size of the vector is 20 elements and I'm trying to do a sum of 5 elements from the current position.

Something like: sum the elements from 1 to 5, 2 to 6, 3 to 7 and so on.

I thought that I could do a for nested loop, like this one below:

for (int a = 0; a < numVec.size(); a  ) {
    for (int b = a; b < numVec.size(); b  )
    {
        if (aux < 5) {
            cout << "B: " << b << endl;
            sum  = numVec[b].num;
        }

        if (aux > 4) {
            aux = 0;
            sumAux= sum;
            sum= 0;
            break;
        }

        aux  ;
    }
    cout << "Sum: " << sumAux<< endl;
}

But I'm having some problems when I get the 15th position, everything goes wrong and I can't figure out why.

everything goes wrong

If you can help me, I thank you very much.

CodePudding user response:

It will help you a lot, if you think for a longer time before start to code something. Maybe you can take a piece of paper and write something down.

Then, it will very much help you, if you choose long and speaking variable names.

So, let us make a picuture. We write some test values and their index in the vector, where they are stored. Please remeber. Indices start with 0 in C .

Value:   21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
Index:    0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19

So, and if we now want to build the sums for 5 values each, then we need to add

Index   0  1  2  3  4      Value: 21 22 23 24 25
Index   1  2  3  4  5      Value: 22 23 24 25 26
Index   2  3  4  5  6      Value: 23 24 25 26 27

. . . 

Index   14 15 16 17 18     Value: 35 36 37 38 39
Index   15 16 17 18 19     Value: 36 37 38 39 40

So, you can see. We have a start index that always will be incremented by 1. Beginning with this start index, we will always add up 5 values. But we must end this process, as you can see above at index 15, so 20 - 5.So, always, size of the whole array - the size of the subarray.

So, let us first solve this problem we can do it strigh forward:

#include <iostream>
#include <vector>

int main() {
    // Our test data to play with
    std::vector<int> data = { 21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40 };
    
    // This is the size of the subarray. So the number of values that we want to sum up
    int sizeOfSubarray = 5;

    // And because we have a subarray size, the last summation starts at this index
    int lastIndex = data.size() - sizeOfSubarray;

    // So, now iterate over all data that needs to be summed up
    for (int startIndex = 0; startIndex <= lastIndex;   startIndex) {

        // Because we have a new start index now, we start also with a 0 sum
        int sum = 0;

        // Calculate the end index of the sub array
        int endIndexOfSubarray = startIndex   sizeOfSubarray;
        for (int sumIndex = startIndex; sumIndex < endIndexOfSubarray;   sumIndex) {

            // Some debug output
            std::cout << "Startindex: " << startIndex << "\tSumindex: " << sumIndex << "\tValue: " << data[sumIndex] << '\n';

            // Calculate the subarray sum
            sum = sum   data[sumIndex];
        }
        // Show the subarray sum
        std::cout << "Sum: " << sum << '\n';
    }
}

OK, understood. What, if we want also to add up the end of the values of the array? So, what if the startindex will rund over the complete array. Let us look at this.

Index   16 17 18 19  ?     Value: 37 38 39  40 ?
Index   17 18 19  ?  ?     Value: 38 39 40  ?  ?
Index   18 19  ?  ?  ?     Value: 39 40  ?  ?  ?
Index   19  ?  ?  ?  ?     Value: 40  ?  ?  ?  ?

You can see, that the start index runs until < 20. So < size of vector.

And if the is the end index of the summation is > 19, so >= the sizeof the vector, we can limit it to 19,

This we can either calculate or use a simple if statement.

Then the code would look like that

#include <iostream>
#include <vector>

int main() {
    // Our test data to play with
    std::vector<int> data = { 21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40 };
    
    // This is the size of the subarray. So the number of values that we want to sum up
    int sizeOfSubarray = 5;

    // So, now iterate over all data that needs to be summed up
    for (int startIndex = 0; startIndex < data.size();   startIndex) {

        // Because we have a new start index now, we start also with a 0 sum
        int sum = 0;

        // Calculate the end index of the sub array
        int endIndexOfSubarray = startIndex   sizeOfSubarray;

        // If this index is too big ( > 20) then limit it to 20
        if (endIndexOfSubarray > data.size()) {
            endIndexOfSubarray = data.size();
        }
        // Claculate sum of sub array
        for (int sumIndex = startIndex; sumIndex < endIndexOfSubarray;   sumIndex) {

            // Some debug output
            std::cout << "Startindex: " << startIndex << "\tSumindex: " << sumIndex << "\tValue: " << data[sumIndex] << '\n';

            // Calculate the subarray sum
            sum = sum   data[sumIndex];
        }
        // Show the subarray sum
        std::cout << "Sum: " << sum << '\n';
    }
}

I hope, this explanation helps

CodePudding user response:

One option is to have the inner loop range from 0-5

for (int a = 0; a < numVec.size(); a  ) {
    int sum = 0;
    for (int b = 0; b < 5 && a   b < numVec.size(); b  ) {
         sum  = numVec[a   b];
    }
    std::cout << sum << "\n";
}

Another option is to use std::accumulate

for (auto a = numVec.begin(); a < numVec.end(); a  ) {
    std::cout << std::accumulate(a, std::min(a   5, numVec.end()), 0) << '\n';
}

Also, mentioned in the comments by @Bathsheba is to keep a running total, which is O(n).

int sum = 0;
for (int a = 0; a < 5 && a < numVec.size(); a  ) sum  = numVec[a];
std::cout << sum << '\n';
for (int a = 5; a < numVec.size(); a  ) {
    sum = sum - numVec[a - 5]   numVec[a];
    std::cout << sum << '\n';
}

CodePudding user response:

This is considered to be the rolling sum etc. You could write a template that manipulates a binary function on the vector specifying the window:

# include <iostream>
# include <numeric>
# include <vector>
# include <functional> 
using namespace std;

template<class T, class Lambda>
vector<T> roll_fun(vector<T> vec, int window, Lambda&& func, T init){
    int final_size =  vec.size() - window   1;
    vector<T> result(final_size);
    for (int k = 0; k < final_size; k  )
      result[k] = accumulate(vec.begin()   k, vec.begin()   k   window, init, func);
    return result;
};


int main() 
{  vector<double> myvec{1,2,2.3,3,4,5,6,7,8,9,1,2,3,4,5,6,7};

    //rolling sum
    vector<double> v = roll_fun<double>(myvec, 5,plus<double>(), 0.0);
    for(auto i: v) cout<<i<<' ';
    cout<<endl;
    
    // rolling mean
    vector<double> v1 = roll_fun<double>(myvec, 5,[](double x, double y){return x y/5;}, 0);
    for(auto i: v1) cout<<i<<' ';
    cout<<endl;
    
     //rolling max
    vector<double> v2 = roll_fun<double>(myvec, 5,[](double x, double y){return x>y?x:y;}, 0.0);
    for(auto i: v2) cout<<i<<' ';
    cout<<endl;
    
    return 0;
}

CodePudding user response:

The whole aux and sumAux handling is making your logic more complicated than it needs to be.

Try something more like this:

#include <algorithm>

const size_t size = numVec.size();
const size_t increment = 5;

for (size_t a = 0; a < size;   a)
{
    size_t stop = a   std::min(size-a, increment);

    sum = 0;
    for (size_t b = a; b < stop;   b)
        sum  = numVec[b].num;

    cout << "Sum: " << sum << endl;
}

Online Demo

Alternatively:

#include <algorithm>
#include <numeric>

auto end = numVec.end();
decltype(numVec)::difference_type increment = 5;

for (auto start = numVec.begin(); start != end;   start)
{
    auto stop = start   std::min(end-start, increment);

    sum = std::accumulate(start, stop, 0,
        [](auto a, const auto &elem){ return a   elem.num; }
    );

    cout << "Sum: " << sum << endl;
}

Online Demo

  •  Tags:  
  • c
  • Related