0

I want to implement code that adds up an array of ints until it meets a certain condition. Here's my code:

int x [5];

int GetIndex (int val)
{
    int i; 
    int xtotal=0; 

    for (i=0; i < 5; ++i) {
        if (xtotal > val) 
            break;
        xtotal += x [i];
    }


    return i;    
}

I'm using c++03. I came across the stl accumulate function but I don't want to add up everything. I want to add up values until it becomes greater than the input. The array is just an example and may be replaced by a vector or whatever.

Dean
  • 138
  • 2
  • 7
  • possible duplicate of [Implementations of count\_until and accumulate\_until?](http://stackoverflow.com/questions/20783342/implementations-of-count-until-and-accumulate-until) – Jarod42 Apr 21 '14 at 13:36

2 Answers2

1

You could write your own. Here's the one from http://www.richelbilderbeek.nl/CppAccumulate_if.htm

template
   <
   typename InputIterator,
   typename ElementType,
   typename Predicate
   >
 const ElementType accumulate_if(
   InputIterator first,
   const InputIterator last,
   ElementType init,
   const Predicate predicate)
 {
   for (; first != last; ++first)
     if (predicate(*first)) init += *first;
   return init;
 }

He also has one that takes a binary operation in case you want to do something besides addition.

Jerry Jeremiah
  • 9,045
  • 2
  • 23
  • 32
  • The algorithm as presented requires evaluating *all* inputs, regardless of whether the value is to be used or not. The code in the question is not really an `accumulate_if`, but rather `accumulate_until` (i.e. once the condition becomes true, the loop terminates). Other than that, you should avoid returning a `const` value, and the `const` in the two arguments is a bit of a code smell also. If the algorithm is not allowed to modify the predicate, why copy in the first place? – David Rodríguez - dribeas Apr 21 '14 at 13:10
1

You may use something like (c++03):

template<class InputIt, class T>
std::pair<InputIt, T>
accumulate_until(InputIt begin, InputIt end, T value, T thresold_value)
{
    for (InputIt it = begin; it != end; ++it) {
        value += *it;
        if (thresold_value < value) {
            return std::make_pair(it, value);
        }
    }
    return std::make_pair(end, value);
}

Or a more generic solution (c++03):

namespace detail
{
    template <typename T, typename Pred>
    class InternalPredicate
    {
    public:
        InternalPredicate(T& value, Pred& pred) : value(value), pred(pred) {}

        bool operator () (const T& t) {
            value += t;
            return pred(value);
        }
    private:
        T& value;
        Pred& pred;
    };
}

template<class InputIt, class T, class Pred>
std::pair<InputIt, T>
accumulate_until(InputIt begin, InputIt end, T value, Pred pred)
{
    InputIt it = std::find_if(begin, end, detail::InternalPredicate<T, Pred>(value, pred));
    return std::make_pair(it, value);
}

or in C++11:

template<class InputIt, class T, class Pred>
std::pair<InputIt, value>
accumulate_until(InputIt begin, InputIt end, T value, Pred pred)
{
    auto internal_pred = [&value, &pred] (const T& t) {
        value += t;
        return pred(value);
    };
    InputIt it = std::find_if(begin, end, internal_pred);
    return std::make_pair(it, value);
}
Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • OP is using C++03 btw, so a version w/o lambdas might be better. Also, although I understand your algorithm is from TemplateRex' question, I think using a raw loop is acceptable here and maybe simpler (especially w/o lambdas). – dyp Apr 21 '14 at 14:59
  • @dyp: I agree that the generic c++03 is more complicated than the simple loop or with the lambda of c++11 :/ – Jarod42 Apr 21 '14 at 15:33
  • I meant something like [this](http://coliru.stacked-crooked.com/a/132a83cc7a2d969c); not sure what to think about mutating predicates (language-laywer-safe?) – dyp Apr 21 '14 at 17:03
  • @dyp: Your sample use predicate on iterator and not on the accumulated value, so it may be rewritten as `std::accumulate(begin, std::find_if(begin, end, pred), 0);` – Jarod42 Apr 21 '14 at 17:15
  • m( right, here's a fixed version: http://coliru.stacked-crooked.com/a/421df53fa4f4268f `accumulate` plus `find_if` requires multi-pass. – dyp Apr 21 '14 at 17:32