I have a trouble understanding std::accumulate. Can it be used to add up the values at only even indices from a vector? 
int rob(vector<int>& nums) {
    int a = std::accumulate(nums.begin(), nums.end(), 0);
   std::cout <<" a: " <<a; 
   return a;
}
So if I have a vector y = {1, 2, 3, 4}
How could I change the above code, so that std::accumulate only iterates over indices [0] and [2]. Is that even possible using std::accumulate?
You have a couple of choices. The quick and (really) dirty way is to walk across the whole collection, and invoke a function that keeps track of the current index, and ignores the values at the odd indices. It works, but it's ugly at best, and more importantly it's wrong on a rather fundamental level, forcing what's supposed to be an accumulation function to take responsibility for doing iteration. In short, this is much more of a problem than a solution.
The clean way would be to realize that visiting every other item in the collection is really about iteration, not about a specific algorithm (std::accumulate or any other). So what we should be using here is an iterator that visits the items we want to visit. Here's a minimal implementation:
#include <vector>
#include <iterator>
#include <iostream>
#include <numeric>
template <class Iterator>
class n_iterator { 
     Iterator i;
     size_t n;
public:
    // We construct this iterator from some other iterator, plus a "step" value
    // to tell us how many items to skip forward when `++` is applied.
    n_iterator(Iterator i, size_t n) : i(i), n(n) {}
    // When you dereference this iterator, it's equivalent to dereferencing
    // the underlying iterator.
    typename std::iterator_traits<Iterator>::value_type operator *() { return *i; }
    // ...but when you increment it, you move ahead N places instead of 1.
    n_iterator &operator++() { std::advance(i, n); return *this; }
    // iterator comparisons just compare the underlying iterators.
    bool operator==(n_iterator const &other) const { return i == other.i; }
    bool operator!=(n_iterator const &other) const { return i != other.i; }
};
int main() { 
    std::vector<int> y { 1, 2, 3, 4};
    auto total = std::accumulate(y.begin(), y.end(), 0);
    std::cout << "total: " << total << "\n";
    auto skip_total = std::accumulate(n_iterator(y.begin(), 2), n_iterator(y.end(), 2), 0);
    std::cout << "Skipped total: " << skip_total << "\n";
}
This implementation seems to suffice for g++ 7.1 to compile the code, but for real use, you should probably implement the entire interface for an iterator (e.g., as a minimum, it should really have definitions for value_type, reference, etc.)
For the moment, this also supplies only a forward iterator, regardless of the underlying iterator. Depending on the situation (and category of underlying iterator) you could also support bidirectional and/or random iteration.
Here you are
int rob( const vector<int>& nums) {
    int i = 0;
    int a = std::accumulate(nums.begin(), nums.end(), 0,
                            [&i]( const auto &acc, const auto &value )
                            {
                                return ( i ^= 1 ) ? acc + value : acc;
                            } );
   std::cout <<" a: " <<a; 
   return a;
}
Here is a demonstrative program
#include <iostream>
#include <vector>
#include <iterator>
#include <numeric>
int rob( const std::vector<int> &nums )
{
    int i = 0;
    int a = std::accumulate( std::begin( nums ), std::end( nums ), 0,
                             [&i]( const auto &acc, const auto &value )
                             {
                                return ( i ^= 1 ) ? acc + value : acc;
                             } );
   return a;
}
int main() 
{
    std::vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    std::cout << rob( v ) << '\n';
    return 0;
}
Its output is
20
You can add one more parameter to the function that you could select whether to sum even or odd numbers. For example
#include <iostream>
#include <vector>
#include <iterator>
#include <numeric>
int rob( const std::vector<int> &nums, bool odds = false )
{
    int i = odds;
    int a = std::accumulate( std::begin( nums ), std::end( nums ), 0,
                             [&i]( const auto &acc, const auto &value )
                             {
                                return ( i ^= 1 ) ? acc + value : acc;
                             } );
   return a;
}
int main() 
{
    std::vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    std::cout << rob( v ) << '\n';
    std::cout << rob( v, true ) << '\n';
    return 0;
}
The program output is
20
25
In this case you can remove the declaration of the variable i. For example
#include <iostream>
#include <vector>
#include <iterator>
#include <numeric>
int rob( const std::vector<int> &nums, bool odds = false )
{
    int a = std::accumulate( std::begin( nums ), std::end( nums ), 0,
                             [&odds]( const auto &acc, const auto &value )
                             {
                                return ( odds = !odds ) ? acc + value : acc;
                             } );
   return a;
}
int main() 
{
    std::vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    std::cout << rob( v ) << '\n';
    std::cout << rob( v, true ) << '\n';
    return 0;
}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With