// Quicksort using Djikstra's 3-way partition.
#include <functional>
#include <algorithm>
#include <random>
#include <chrono>
#include <iostream>
using namespace std;
int randint(int a, int b)
{
thread_local default_random_engine re(random_device{}());
uniform_int_distribution<> pick(a, b);
return pick(re);
}
void timeit(function<void()> thunk)
{
using clock = chrono::steady_clock;
clock::time_point t = clock::now();
thunk();
chrono::duration<double> elapsed = clock::now() - t;
cout << "Elapsed: " << fixed << elapsed.count() << "s\n";
}
template<typename In>
ostream& ostream_join(ostream& os, In first, In last, string sep)
{
if (first != last)
{
for (;;)
{
os << *first;
if (++first == last) break;
os << sep;
}
}
return os;
}
template<typename T>
ostream& operator<<(ostream& os, const vector<T>& a)
{
os << '[';
ostream_join(os, a.begin(), a.end(), ", ");
os << ']';
return os;
}
// Sort.
template<typename Bi, typename Compare, typename T>
pair<Bi, Bi> partition3(Bi first, Bi last, Compare comp, T pivot)
{
for (Bi i = first; i != last;)
{
if (comp(*i, pivot))
{
iter_swap(first++, i++);
}
else if (comp(pivot, *i))
{
iter_swap(i, --last);
}
else
{
i++;
}
}
return {first, last};
}
template<typename Ran, typename Compare>
void quicksort(Ran first, Ran last, Compare comp)
{
if (auto n = distance(first, last); n >= 2)
{
auto eq = partition3(first, last, comp, *next(first, randint(0, n-1)));
quicksort(first, eq.first, comp);
quicksort(eq.second, last, comp);
}
}
template<typename Ran>
void quicksort(Ran first, Ran last)
{
quicksort(first, last, less<typename iterator_traits<Ran>::value_type>());
}
// Main.
void test1(int n)
{
vector<int> t(n);
generate(t.begin(), t.end(), bind(randint, 1-n, n-1));
vector<int> u = t;
sort(u.begin(), u.end());
vector<int> v = t;
quicksort(v.begin(), v.end());
if (u == v)
{
cout << "Pass: " << n << endl;
}
else
{
cout << "Fail: " << n << endl;
for (auto x : {t, u, v})
cout << x << endl;
}
}
void time1(int n)
{
vector<int> t(n);
generate(t.begin(), t.end(), bind(randint, 1-n, n-1));
timeit([&]{
quicksort(t.begin(), t.end());
});
}
void p2call(int j, int k, function<void(int)> f)
{
int m = 1;
for (int i = 0; i < j; i++)
m *= 2;
for (int i = j; i < k; i++)
{
f(m-1);
m *= 2;
}
}
int main()
{
p2call(0, 6, test1);
p2call(16, 22, time1);
}
Ly8gUXVpY2tzb3J0IHVzaW5nIERqaWtzdHJhJ3MgMy13YXkgcGFydGl0aW9uLgoKI2luY2x1ZGUgPGZ1bmN0aW9uYWw+CiNpbmNsdWRlIDxhbGdvcml0aG0+CiNpbmNsdWRlIDxyYW5kb20+CiNpbmNsdWRlIDxjaHJvbm8+CiNpbmNsdWRlIDxpb3N0cmVhbT4KdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCmludCByYW5kaW50KGludCBhLCBpbnQgYikKewogICAgdGhyZWFkX2xvY2FsIGRlZmF1bHRfcmFuZG9tX2VuZ2luZSByZShyYW5kb21fZGV2aWNle30oKSk7CiAgICB1bmlmb3JtX2ludF9kaXN0cmlidXRpb248PiBwaWNrKGEsIGIpOwogICAgcmV0dXJuIHBpY2socmUpOwp9Cgp2b2lkIHRpbWVpdChmdW5jdGlvbjx2b2lkKCk+IHRodW5rKQp7CiAgICB1c2luZyBjbG9jayA9IGNocm9ubzo6c3RlYWR5X2Nsb2NrOwogICAgY2xvY2s6OnRpbWVfcG9pbnQgdCA9IGNsb2NrOjpub3coKTsKICAgIHRodW5rKCk7CiAgICBjaHJvbm86OmR1cmF0aW9uPGRvdWJsZT4gZWxhcHNlZCA9IGNsb2NrOjpub3coKSAtIHQ7CiAgICBjb3V0IDw8ICJFbGFwc2VkOiAiIDw8IGZpeGVkIDw8IGVsYXBzZWQuY291bnQoKSA8PCAic1xuIjsKfQoKdGVtcGxhdGU8dHlwZW5hbWUgSW4+Cm9zdHJlYW0mIG9zdHJlYW1fam9pbihvc3RyZWFtJiBvcywgSW4gZmlyc3QsIEluIGxhc3QsIHN0cmluZyBzZXApCnsKICAgIGlmIChmaXJzdCAhPSBsYXN0KQogICAgewogICAgICAgIGZvciAoOzspCiAgICAgICAgewogICAgICAgICAgICBvcyA8PCAqZmlyc3Q7CiAgICAgICAgICAgIGlmICgrK2ZpcnN0ID09IGxhc3QpIGJyZWFrOwogICAgICAgICAgICBvcyA8PCBzZXA7CiAgICAgICAgfQogICAgfQogICAgcmV0dXJuIG9zOwp9Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBUPgpvc3RyZWFtJiBvcGVyYXRvcjw8KG9zdHJlYW0mIG9zLCBjb25zdCB2ZWN0b3I8VD4mIGEpCnsKICAgIG9zIDw8ICdbJzsKICAgIG9zdHJlYW1fam9pbihvcywgYS5iZWdpbigpLCBhLmVuZCgpLCAiLCAiKTsKICAgIG9zIDw8ICddJzsKICAgIHJldHVybiBvczsKfQoKLy8gU29ydC4KCnRlbXBsYXRlPHR5cGVuYW1lIEJpLCB0eXBlbmFtZSBDb21wYXJlLCB0eXBlbmFtZSBUPgpwYWlyPEJpLCBCaT4gcGFydGl0aW9uMyhCaSBmaXJzdCwgQmkgbGFzdCwgQ29tcGFyZSBjb21wLCBUIHBpdm90KQp7CiAgICBmb3IgKEJpIGkgPSBmaXJzdDsgaSAhPSBsYXN0OykKICAgIHsKICAgICAgICBpZiAoY29tcCgqaSwgcGl2b3QpKQogICAgICAgIHsKICAgICAgICAgICAgaXRlcl9zd2FwKGZpcnN0KyssIGkrKyk7CiAgICAgICAgfQogICAgICAgIGVsc2UgaWYgKGNvbXAocGl2b3QsICppKSkKICAgICAgICB7CiAgICAgICAgICAgIGl0ZXJfc3dhcChpLCAtLWxhc3QpOwogICAgICAgIH0KICAgICAgICBlbHNlCiAgICAgICAgewogICAgICAgICAgICBpKys7CiAgICAgICAgfQogICAgfQogICAgcmV0dXJuIHtmaXJzdCwgbGFzdH07Cn0KCnRlbXBsYXRlPHR5cGVuYW1lIFJhbiwgdHlwZW5hbWUgQ29tcGFyZT4Kdm9pZCBxdWlja3NvcnQoUmFuIGZpcnN0LCBSYW4gbGFzdCwgQ29tcGFyZSBjb21wKQp7CiAgICBpZiAoYXV0byBuID0gZGlzdGFuY2UoZmlyc3QsIGxhc3QpOyBuID49IDIpCiAgICB7CiAgICAgICAgYXV0byBlcSA9IHBhcnRpdGlvbjMoZmlyc3QsIGxhc3QsIGNvbXAsICpuZXh0KGZpcnN0LCByYW5kaW50KDAsIG4tMSkpKTsKICAgICAgICBxdWlja3NvcnQoZmlyc3QsIGVxLmZpcnN0LCBjb21wKTsKICAgICAgICBxdWlja3NvcnQoZXEuc2Vjb25kLCBsYXN0LCBjb21wKTsKICAgIH0KfQoKdGVtcGxhdGU8dHlwZW5hbWUgUmFuPgp2b2lkIHF1aWNrc29ydChSYW4gZmlyc3QsIFJhbiBsYXN0KQp7CiAgICBxdWlja3NvcnQoZmlyc3QsIGxhc3QsIGxlc3M8dHlwZW5hbWUgaXRlcmF0b3JfdHJhaXRzPFJhbj46OnZhbHVlX3R5cGU+KCkpOwp9CgovLyBNYWluLgoKdm9pZCB0ZXN0MShpbnQgbikKewogICAgdmVjdG9yPGludD4gdChuKTsKICAgIGdlbmVyYXRlKHQuYmVnaW4oKSwgdC5lbmQoKSwgYmluZChyYW5kaW50LCAxLW4sIG4tMSkpOwogICAgdmVjdG9yPGludD4gdSA9IHQ7CiAgICBzb3J0KHUuYmVnaW4oKSwgdS5lbmQoKSk7CiAgICB2ZWN0b3I8aW50PiB2ID0gdDsKICAgIHF1aWNrc29ydCh2LmJlZ2luKCksIHYuZW5kKCkpOwogICAgaWYgKHUgPT0gdikKICAgIHsKICAgICAgICBjb3V0IDw8ICJQYXNzOiAiIDw8IG4gPDwgZW5kbDsKICAgIH0KICAgIGVsc2UKICAgIHsKICAgICAgICBjb3V0IDw8ICJGYWlsOiAiIDw8IG4gPDwgZW5kbDsKICAgICAgICBmb3IgKGF1dG8geCA6IHt0LCB1LCB2fSkKICAgICAgICAgICAgY291dCA8PCB4IDw8IGVuZGw7CiAgICB9Cn0KCnZvaWQgdGltZTEoaW50IG4pCnsKICAgIHZlY3RvcjxpbnQ+IHQobik7CiAgICBnZW5lcmF0ZSh0LmJlZ2luKCksIHQuZW5kKCksIGJpbmQocmFuZGludCwgMS1uLCBuLTEpKTsKICAgIHRpbWVpdChbJl17CiAgICAgICAgcXVpY2tzb3J0KHQuYmVnaW4oKSwgdC5lbmQoKSk7CiAgICB9KTsKfQoKdm9pZCBwMmNhbGwoaW50IGosIGludCBrLCBmdW5jdGlvbjx2b2lkKGludCk+IGYpCnsKICAgIGludCBtID0gMTsKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgajsgaSsrKQogICAgICAgIG0gKj0gMjsKICAgIGZvciAoaW50IGkgPSBqOyBpIDwgazsgaSsrKQogICAgewogICAgICAgIGYobS0xKTsKICAgICAgICBtICo9IDI7CiAgICB9Cn0KCmludCBtYWluKCkKewogICAgcDJjYWxsKDAsIDYsIHRlc3QxKTsKICAgIHAyY2FsbCgxNiwgMjIsIHRpbWUxKTsKfQ==