#include <functional>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <ostream>
#include <string>
using namespace std;
// _____________________[ recursive stable group ]___________________________ //
// stable merge of adjacent groups
template<typename BidirectionalIterator>
void merge_groups(BidirectionalIterator first,BidirectionalIterator middle,BidirectionalIterator last)
{
typedef reverse_iterator<BidirectionalIterator> ReverseIterator;
BidirectionalIterator i=middle,current,sub_last,next_to_same;
while(i != last)
{
current = i++;
sub_last=find(i,last,*current);
if(sub_last!=last)
i = sub_last;
next_to_same = find(ReverseIterator(current),ReverseIterator(first),*current).base();
if(next_to_same!=first)
rotate(next_to_same,current,i);
}
}
template<typename BidirectionalIterator>
void stable_group(BidirectionalIterator first,BidirectionalIterator last)
{
if(first!=last)
{
BidirectionalIterator middle=first;
typename iterator_traits<BidirectionalIterator>::difference_type range_size = distance(first,last);
if(range_size>2)
{
advance(middle,range_size/2);
stable_group(first,middle);
stable_group(middle,last);
merge_groups(first,middle,last);
}
}
}
// __________________________________________________________________________ //
template<typename BidirectionalIterator>
void group_gold(BidirectionalIterator first,BidirectionalIterator last)
{
typedef typename iterator_traits<BidirectionalIterator>::value_type value_type;
while(first!=last)
first = stable_partition(first, last, bind1st(equal_to<value_type>(),*first));
}
template<typename Range>
void test_with_gold(const Range &s)
{
Range p = s;
do
{
next_permutation(begin(p),end(p));
auto gold = p, recursive = p;
group_gold(begin(gold),end(gold));
stable_group(begin(recursive),end(recursive));
if(gold!=recursive)
{
cout << "Error, gold and recursive result differs" << endl;
cout << "Gold=" << gold << endl;
cout << "Recursive=" << recursive << endl;
}
}while(p!=s);
}
int main()
{
string tests[] =
{
"vvabcbbcc",
"asdfrrafdsr",
"abcdefgijkl",
"010101010101",
"totobobolol"
};
for(auto &&s : tests)
{
test_with_gold(s);
stable_group(begin(s),end(s));
cout << s << endl;
}
}
I2luY2x1ZGUgPGZ1bmN0aW9uYWw+CiNpbmNsdWRlIDxhbGdvcml0aG0+CiNpbmNsdWRlIDxpb3N0cmVhbT4KI2luY2x1ZGUgPGl0ZXJhdG9yPgojaW5jbHVkZSA8b3N0cmVhbT4KI2luY2x1ZGUgPHN0cmluZz4KCnVzaW5nIG5hbWVzcGFjZSBzdGQ7CgovLyBfX19fX19fX19fX19fX19fX19fX19bIHJlY3Vyc2l2ZSBzdGFibGUgZ3JvdXAgXV9fX19fX19fX19fX19fX19fX19fX19fX19fXyAvLwoKLy8gc3RhYmxlIG1lcmdlIG9mIGFkamFjZW50IGdyb3Vwcwp0ZW1wbGF0ZTx0eXBlbmFtZSBCaWRpcmVjdGlvbmFsSXRlcmF0b3I+CnZvaWQgbWVyZ2VfZ3JvdXBzKEJpZGlyZWN0aW9uYWxJdGVyYXRvciBmaXJzdCxCaWRpcmVjdGlvbmFsSXRlcmF0b3IgbWlkZGxlLEJpZGlyZWN0aW9uYWxJdGVyYXRvciBsYXN0KQp7CiAgICB0eXBlZGVmIHJldmVyc2VfaXRlcmF0b3I8QmlkaXJlY3Rpb25hbEl0ZXJhdG9yPiBSZXZlcnNlSXRlcmF0b3I7CiAgICBCaWRpcmVjdGlvbmFsSXRlcmF0b3IgaT1taWRkbGUsY3VycmVudCxzdWJfbGFzdCxuZXh0X3RvX3NhbWU7CiAgICB3aGlsZShpICE9IGxhc3QpCiAgICB7CiAgICAgICAgY3VycmVudCA9IGkrKzsKICAgICAgICBzdWJfbGFzdD1maW5kKGksbGFzdCwqY3VycmVudCk7CiAgICAgICAgaWYoc3ViX2xhc3QhPWxhc3QpCiAgICAgICAgICAgIGkgPSBzdWJfbGFzdDsKICAgICAgICBuZXh0X3RvX3NhbWUgPSBmaW5kKFJldmVyc2VJdGVyYXRvcihjdXJyZW50KSxSZXZlcnNlSXRlcmF0b3IoZmlyc3QpLCpjdXJyZW50KS5iYXNlKCk7CiAgICAgICAgaWYobmV4dF90b19zYW1lIT1maXJzdCkKICAgICAgICAgICByb3RhdGUobmV4dF90b19zYW1lLGN1cnJlbnQsaSk7CiAgICB9Cn0KCnRlbXBsYXRlPHR5cGVuYW1lIEJpZGlyZWN0aW9uYWxJdGVyYXRvcj4Kdm9pZCBzdGFibGVfZ3JvdXAoQmlkaXJlY3Rpb25hbEl0ZXJhdG9yIGZpcnN0LEJpZGlyZWN0aW9uYWxJdGVyYXRvciBsYXN0KQp7CiAgICBpZihmaXJzdCE9bGFzdCkKICAgIHsKICAgICAgICBCaWRpcmVjdGlvbmFsSXRlcmF0b3IgbWlkZGxlPWZpcnN0OwogICAgICAgIHR5cGVuYW1lIGl0ZXJhdG9yX3RyYWl0czxCaWRpcmVjdGlvbmFsSXRlcmF0b3I+OjpkaWZmZXJlbmNlX3R5cGUgcmFuZ2Vfc2l6ZSA9IGRpc3RhbmNlKGZpcnN0LGxhc3QpOwogICAgICAgIGlmKHJhbmdlX3NpemU+MikKICAgICAgICB7CiAgICAgICAgICAgIGFkdmFuY2UobWlkZGxlLHJhbmdlX3NpemUvMik7CiAgICAgICAgICAgIHN0YWJsZV9ncm91cChmaXJzdCxtaWRkbGUpOwogICAgICAgICAgICBzdGFibGVfZ3JvdXAobWlkZGxlLGxhc3QpOwogICAgICAgICAgICBtZXJnZV9ncm91cHMoZmlyc3QsbWlkZGxlLGxhc3QpOwogICAgICAgIH0KICAgIH0KfQoKLy8gX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18gLy8KCnRlbXBsYXRlPHR5cGVuYW1lIEJpZGlyZWN0aW9uYWxJdGVyYXRvcj4Kdm9pZCBncm91cF9nb2xkKEJpZGlyZWN0aW9uYWxJdGVyYXRvciBmaXJzdCxCaWRpcmVjdGlvbmFsSXRlcmF0b3IgbGFzdCkKewogICAgdHlwZWRlZiB0eXBlbmFtZSBpdGVyYXRvcl90cmFpdHM8QmlkaXJlY3Rpb25hbEl0ZXJhdG9yPjo6dmFsdWVfdHlwZSB2YWx1ZV90eXBlOwogICAgd2hpbGUoZmlyc3QhPWxhc3QpCiAgICAgICAgZmlyc3QgPSBzdGFibGVfcGFydGl0aW9uKGZpcnN0LCBsYXN0LCBiaW5kMXN0KGVxdWFsX3RvPHZhbHVlX3R5cGU+KCksKmZpcnN0KSk7Cn0KCnRlbXBsYXRlPHR5cGVuYW1lIFJhbmdlPgp2b2lkIHRlc3Rfd2l0aF9nb2xkKGNvbnN0IFJhbmdlICZzKQp7CiAgICBSYW5nZSBwID0gczsKICAgIGRvCiAgICB7CiAgICAgICAgbmV4dF9wZXJtdXRhdGlvbihiZWdpbihwKSxlbmQocCkpOwogICAgICAgIGF1dG8gZ29sZCA9IHAsIHJlY3Vyc2l2ZSA9IHA7CiAgICAgICAgZ3JvdXBfZ29sZChiZWdpbihnb2xkKSxlbmQoZ29sZCkpOwogICAgICAgIHN0YWJsZV9ncm91cChiZWdpbihyZWN1cnNpdmUpLGVuZChyZWN1cnNpdmUpKTsKICAgICAgICBpZihnb2xkIT1yZWN1cnNpdmUpCiAgICAgICAgewogICAgICAgICAgICBjb3V0IDw8ICJFcnJvciwgZ29sZCBhbmQgcmVjdXJzaXZlIHJlc3VsdCBkaWZmZXJzIiA8PCBlbmRsOwogICAgICAgICAgICBjb3V0IDw8ICJHb2xkPSIgPDwgZ29sZCA8PCBlbmRsOwogICAgICAgICAgICBjb3V0IDw8ICJSZWN1cnNpdmU9IiA8PCByZWN1cnNpdmUgPDwgZW5kbDsKICAgICAgICB9CiAgICB9d2hpbGUocCE9cyk7Cn0KCmludCBtYWluKCkKewogICAgc3RyaW5nIHRlc3RzW10gPQogICAgewogICAgICAgICJ2dmFiY2JiY2MiLAogICAgICAgICJhc2RmcnJhZmRzciIsCiAgICAgICAgImFiY2RlZmdpamtsIiwKICAgICAgICAiMDEwMTAxMDEwMTAxIiwKICAgICAgICAidG90b2JvYm9sb2wiCiAgICB9OwogICAgZm9yKGF1dG8gJiZzIDogdGVzdHMpCiAgICB7CiAgICAgICAgdGVzdF93aXRoX2dvbGQocyk7CiAgICAgICAgc3RhYmxlX2dyb3VwKGJlZ2luKHMpLGVuZChzKSk7CiAgICAgICAgY291dCA8PCBzIDw8IGVuZGw7CiAgICB9Cn0=