#include <algorithm>
#include <iterator>
#include <iostream>
using namespace std;
template <
typename MultiPassIOIterator
, typename BinaryPredicate
, typename BinaryMergeTransform
>
MultiPassIOIterator conditionalInPlaceMerge(
MultiPassIOIterator cur
, MultiPassIOIterator end
, BinaryPredicate predicate
, BinaryMergeTransform merge)
{
MultiPassIOIterator next(cur + 1);
while ((cur != end) && (next != end))
{
if (predicate(*cur, *next))
{
*cur = merge(*cur, *next);
move(next + 1, end, next);
--end;
}
else
{
++cur;
++next;
}
}
return (cur != end) ? next : end;
}
// our aggregate structure
struct Aggregate
{
int key_;
unsigned count_;
};
ostream& operator<<(ostream &os, Aggregate a)
{
os << "{ " << a.key_ << ", " << a.count_ << " }";
return os;
}
int main() {
Aggregate aggregates[] = {
{ 12, 35 },
{ 57, 503 },
{ 83, 5675 },
{ 12, 123 },
{ 11, 578 }
};
Aggregate *end(aggregates + (sizeof(aggregates) / sizeof(aggregates[0])));
// first sort
sort(
aggregates, end
, [](Aggregate const &lhs, Aggregate const &rhs){ return lhs.key_ < rhs.key_; });
// now condense
end = conditionalInPlaceMerge(
aggregates
, end
, [](Aggregate const &lhs, Aggregate const &rhs){ return lhs.key_ == rhs.key_; }
, [](Aggregate lhs, Aggregate const &rhs){ lhs.count_ += rhs.count_; return lhs; }
);
ostream_iterator< Aggregate > out_it(cout, "\n");
copy(aggregates, end, out_it);
return 0;
}
I2luY2x1ZGUgPGFsZ29yaXRobT4KCiNpbmNsdWRlIDxpdGVyYXRvcj4KI2luY2x1ZGUgPGlvc3RyZWFtPgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKdGVtcGxhdGUgPAogICAgICB0eXBlbmFtZSBNdWx0aVBhc3NJT0l0ZXJhdG9yCiAgICAsIHR5cGVuYW1lIEJpbmFyeVByZWRpY2F0ZQogICAgLCB0eXBlbmFtZSBCaW5hcnlNZXJnZVRyYW5zZm9ybQo+Ck11bHRpUGFzc0lPSXRlcmF0b3IgY29uZGl0aW9uYWxJblBsYWNlTWVyZ2UoCiAgICAgIE11bHRpUGFzc0lPSXRlcmF0b3IgY3VyCiAgICAsIE11bHRpUGFzc0lPSXRlcmF0b3IgZW5kCiAgICAsIEJpbmFyeVByZWRpY2F0ZSBwcmVkaWNhdGUKICAgICwgQmluYXJ5TWVyZ2VUcmFuc2Zvcm0gbWVyZ2UpCnsKICAgIE11bHRpUGFzc0lPSXRlcmF0b3IgbmV4dChjdXIgKyAxKTsKICAgIHdoaWxlICgoY3VyICE9IGVuZCkgJiYgKG5leHQgIT0gZW5kKSkKICAgIHsKICAgICAgICBpZiAocHJlZGljYXRlKCpjdXIsICpuZXh0KSkKICAgICAgICB7CiAgICAgICAgICAgICpjdXIgPSBtZXJnZSgqY3VyLCAqbmV4dCk7CiAgICAgICAgICAgIG1vdmUobmV4dCArIDEsIGVuZCwgbmV4dCk7CiAgICAgICAgICAgIC0tZW5kOwogICAgICAgIH0KICAgICAgICBlbHNlCiAgICAgICAgewogICAgICAgICAgICArK2N1cjsKICAgICAgICAgICAgKytuZXh0OwogICAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gKGN1ciAhPSBlbmQpID8gbmV4dCA6IGVuZDsKfQoKLy8gb3VyIGFnZ3JlZ2F0ZSBzdHJ1Y3R1cmUKc3RydWN0IEFnZ3JlZ2F0ZQp7CiAgICBpbnQga2V5XzsKICAgIHVuc2lnbmVkIGNvdW50XzsKfTsKb3N0cmVhbSYgb3BlcmF0b3I8PChvc3RyZWFtICZvcywgQWdncmVnYXRlIGEpCnsKICAgIG9zIDw8ICJ7ICIgPDwgYS5rZXlfIDw8ICIsICIgPDwgYS5jb3VudF8gPDwgIiB9IjsKICAgIHJldHVybiBvczsKfQppbnQgbWFpbigpIHsKICAgIEFnZ3JlZ2F0ZSBhZ2dyZWdhdGVzW10gPSB7CiAgICAgICAgeyAxMiwgMzUgfSwKICAgICAgICB7IDU3LCA1MDMgfSwKICAgICAgICB7IDgzLCA1Njc1IH0sCiAgICAgICAgeyAxMiwgMTIzIH0sCiAgICAgICAgeyAxMSwgNTc4IH0KICAgIH07CiAgICBBZ2dyZWdhdGUgKmVuZChhZ2dyZWdhdGVzICsgKHNpemVvZihhZ2dyZWdhdGVzKSAvIHNpemVvZihhZ2dyZWdhdGVzWzBdKSkpOwogICAgLy8gZmlyc3Qgc29ydAogICAgc29ydCgKICAgICAgICAgIGFnZ3JlZ2F0ZXMsIGVuZAogICAgICAgICwgW10oQWdncmVnYXRlIGNvbnN0ICZsaHMsIEFnZ3JlZ2F0ZSBjb25zdCAmcmhzKXsgcmV0dXJuIGxocy5rZXlfIDwgcmhzLmtleV87IH0pOwogICAgLy8gbm93IGNvbmRlbnNlCiAgICBlbmQgPSBjb25kaXRpb25hbEluUGxhY2VNZXJnZSgKICAgICAgICAgIGFnZ3JlZ2F0ZXMKICAgICAgICAsIGVuZAogICAgICAgICwgW10oQWdncmVnYXRlIGNvbnN0ICZsaHMsIEFnZ3JlZ2F0ZSBjb25zdCAmcmhzKXsgcmV0dXJuIGxocy5rZXlfID09IHJocy5rZXlfOyB9CiAgICAgICAgLCBbXShBZ2dyZWdhdGUgbGhzLCBBZ2dyZWdhdGUgY29uc3QgJnJocyl7IGxocy5jb3VudF8gKz0gcmhzLmNvdW50XzsgcmV0dXJuIGxoczsgfQogICAgICAgICk7CiAgICAgICAgCiAgICBvc3RyZWFtX2l0ZXJhdG9yPCBBZ2dyZWdhdGUgPiBvdXRfaXQoY291dCwgIlxuIik7CiAgICBjb3B5KGFnZ3JlZ2F0ZXMsIGVuZCwgb3V0X2l0KTsKICAgIHJldHVybiAwOwp9