#include <tuple>
#include <algorithm>
#include <type_traits>
template <std::size_t A, std::size_t B>
struct compare_pair {
template <typename T>
static void apply(T& t) {
auto& a = std::get<A>(t);
auto& b = std::get<B>(t);
using std::swap;
if (!(a < b))
swap(a, b);
}
};
template <typename... T> struct join_ { using type = decltype(std::tuple_cat(std::declval<T>()...)); };
template <typename... T> using join = typename join_<typename T::type...>::type;
template <std::size_t L, std::size_t R, std::size_t S,
typename = void>
struct oddeven_range_merger {
using type = typename join_<
std::tuple<compare_pair<L, L+S> >,
typename oddeven_range_merger<L+2*S, R, S>::type
>::type;
};
template <std::size_t L, std::size_t R, std::size_t S>
struct oddeven_range_merger<L, R, S,
typename std::enable_if<(L >= R)>::type> {
using type = std::tuple<>;
};
template <std::size_t L, std::size_t R, std::size_t S,
typename = void>
struct oddeven_merger {
using type = join<
oddeven_merger<L, R, 2*S>,
oddeven_merger<L+S, R, 2*S>,
oddeven_range_merger<L+S, R-S, S> >;
};
template <std::size_t L, std::size_t R, std::size_t S>
struct oddeven_merger<L, R, S,
typename std::enable_if<(2*S+1 >= R-L)>::type> {
using type = std::tuple<compare_pair<L, L+S> >;
};
template <std::size_t L, std::size_t R, typename = void>
struct oddeven_sorter {
static constexpr std::size_t M = (L+R)/2;
using type = join<oddeven_sorter<L, M>,
oddeven_sorter<M, R>,
oddeven_merger<L, R, 1> >;
};
template <std::size_t L, std::size_t R>
struct oddeven_sorter<L, R, typename std::enable_if<(R-L <= 1)>::type> {
using type = std::tuple<>;
};
template <std::size_t Size>
using oddeven = typename oddeven_sorter<0, Size>::type;
template <typename... T> struct sorting_network {
template <typename Tuple>
static void apply(Tuple&& t) {
using swallow = int[];
(void)swallow{0, ((void)T::apply(t), 0)...};
}
};
template <typename T> struct make_sorting_network {};
template <typename... T> struct make_sorting_network<std::tuple<T...> > { using type = sorting_network<T...>; };
template <typename T>
void sort_tuple(T&& tuple) {
using network = typename make_sorting_network<oddeven<std::tuple_size<typename std::decay<T>::type >::value> >::type;
network::apply(std::forward<T>(tuple));
}
template <typename... Args>
void sort_arguments(Args&&... args) {
sort_tuple(std::tie(args...));
}
template <std::size_t S>
using swaps_needed = std::tuple_size<oddeven<S> >;
#include <iostream>
#include <array>
#include <utility>
template<class Ch, class Tr, class Tuple, std::size_t... Is>
void print_tuple_impl(std::basic_ostream<Ch,Tr>& os,
const Tuple & t,
std::index_sequence<Is...>) {
using swallow = int[];
(void)swallow{0, (void(os << (Is == 0? "" : ", ") << std::get<Is>(t)), 0)...};
}
template<class Ch, class Tr, class... Args>
decltype(auto) operator<<(std::basic_ostream<Ch, Tr>& os,
const std::tuple<Args...>& t) {
os << "(";
print_tuple_impl(os, t, std::index_sequence_for<Args...>{});
return os << ")";
}
int main()
{
auto t = std::make_tuple(2, 4, 3, 5, 9, 6, 1, 7, 8);
sort_tuple(t);
std::cout << "sorted in "
<< swaps_needed<std::tuple_size<decltype(t)>::value>::value
<< " steps: "
<< t << '\n';
}
I2luY2x1ZGUgPHR1cGxlPgojaW5jbHVkZSA8YWxnb3JpdGhtPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+Cgp0ZW1wbGF0ZSA8c3RkOjpzaXplX3QgQSwgc3RkOjpzaXplX3QgQj4Kc3RydWN0IGNvbXBhcmVfcGFpciB7CiAgdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CiAgc3RhdGljIHZvaWQgYXBwbHkoVCYgdCkgewogICAgYXV0byYgYSA9IHN0ZDo6Z2V0PEE+KHQpOwogICAgYXV0byYgYiA9IHN0ZDo6Z2V0PEI+KHQpOwogICAgdXNpbmcgc3RkOjpzd2FwOwogICAgaWYgKCEoYSA8IGIpKQogICAgICBzd2FwKGEsIGIpOwogIH0KfTsKCnRlbXBsYXRlIDx0eXBlbmFtZS4uLiBUPiBzdHJ1Y3Qgam9pbl8geyB1c2luZyB0eXBlID0gZGVjbHR5cGUoc3RkOjp0dXBsZV9jYXQoc3RkOjpkZWNsdmFsPFQ+KCkuLi4pKTsgfTsKdGVtcGxhdGUgPHR5cGVuYW1lLi4uIFQ+IHVzaW5nIGpvaW4gPSB0eXBlbmFtZSBqb2luXzx0eXBlbmFtZSBUOjp0eXBlLi4uPjo6dHlwZTsKCnRlbXBsYXRlIDxzdGQ6OnNpemVfdCBMLCBzdGQ6OnNpemVfdCBSLCBzdGQ6OnNpemVfdCBTLAogICAgICAgICAgdHlwZW5hbWUgPSB2b2lkPgpzdHJ1Y3Qgb2RkZXZlbl9yYW5nZV9tZXJnZXIgewogIHVzaW5nIHR5cGUgPSB0eXBlbmFtZSBqb2luXzwKICAgIHN0ZDo6dHVwbGU8Y29tcGFyZV9wYWlyPEwsIEwrUz4gPiwKICAgIHR5cGVuYW1lIG9kZGV2ZW5fcmFuZ2VfbWVyZ2VyPEwrMipTLCBSLCBTPjo6dHlwZQogID46OnR5cGU7Cn07CnRlbXBsYXRlIDxzdGQ6OnNpemVfdCBMLCBzdGQ6OnNpemVfdCBSLCBzdGQ6OnNpemVfdCBTPgpzdHJ1Y3Qgb2RkZXZlbl9yYW5nZV9tZXJnZXI8TCwgUiwgUywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGVuYW1lIHN0ZDo6ZW5hYmxlX2lmPChMID49IFIpPjo6dHlwZT4gewogIHVzaW5nIHR5cGUgPSBzdGQ6OnR1cGxlPD47Cn07Cgp0ZW1wbGF0ZSA8c3RkOjpzaXplX3QgTCwgc3RkOjpzaXplX3QgUiwgc3RkOjpzaXplX3QgUywKICAgICAgICAgIHR5cGVuYW1lID0gdm9pZD4Kc3RydWN0IG9kZGV2ZW5fbWVyZ2VyIHsKICAgdXNpbmcgdHlwZSA9IGpvaW48CiAgICAgb2RkZXZlbl9tZXJnZXI8TCwgUiwgMipTPiwKICAgICBvZGRldmVuX21lcmdlcjxMK1MsIFIsIDIqUz4sCiAgICAgb2RkZXZlbl9yYW5nZV9tZXJnZXI8TCtTLCBSLVMsIFM+ID47Cn07Cgp0ZW1wbGF0ZSA8c3RkOjpzaXplX3QgTCwgc3RkOjpzaXplX3QgUiwgc3RkOjpzaXplX3QgUz4Kc3RydWN0IG9kZGV2ZW5fbWVyZ2VyPEwsIFIsIFMsCiAgICAgICAgICAgICAgICAgICAgICB0eXBlbmFtZSBzdGQ6OmVuYWJsZV9pZjwoMipTKzEgPj0gUi1MKT46OnR5cGU+IHsKICB1c2luZyB0eXBlID0gc3RkOjp0dXBsZTxjb21wYXJlX3BhaXI8TCwgTCtTPiA+Owp9OwoKdGVtcGxhdGUgPHN0ZDo6c2l6ZV90IEwsIHN0ZDo6c2l6ZV90IFIsIHR5cGVuYW1lID0gdm9pZD4Kc3RydWN0IG9kZGV2ZW5fc29ydGVyIHsKICBzdGF0aWMgY29uc3RleHByIHN0ZDo6c2l6ZV90IE0gPSAoTCtSKS8yOwogIHVzaW5nIHR5cGUgPSBqb2luPG9kZGV2ZW5fc29ydGVyPEwsIE0+LAogICAgICAgICAgICAgICAgICAgIG9kZGV2ZW5fc29ydGVyPE0sIFI+LAogICAgICAgICAgICAgICAgICAgIG9kZGV2ZW5fbWVyZ2VyPEwsIFIsIDE+ID47Cn07CnRlbXBsYXRlIDxzdGQ6OnNpemVfdCBMLCBzdGQ6OnNpemVfdCBSPgpzdHJ1Y3Qgb2RkZXZlbl9zb3J0ZXI8TCwgUiwgdHlwZW5hbWUgc3RkOjplbmFibGVfaWY8KFItTCA8PSAxKT46OnR5cGU+IHsKICB1c2luZyB0eXBlID0gc3RkOjp0dXBsZTw+Owp9OwoKdGVtcGxhdGUgPHN0ZDo6c2l6ZV90IFNpemU+CnVzaW5nIG9kZGV2ZW4gPSB0eXBlbmFtZSBvZGRldmVuX3NvcnRlcjwwLCBTaXplPjo6dHlwZTsKCnRlbXBsYXRlIDx0eXBlbmFtZS4uLiBUPiBzdHJ1Y3Qgc29ydGluZ19uZXR3b3JrIHsKICB0ZW1wbGF0ZSA8dHlwZW5hbWUgVHVwbGU+CiAgc3RhdGljIHZvaWQgYXBwbHkoVHVwbGUmJiB0KSB7CiAgICB1c2luZyBzd2FsbG93ID0gaW50W107CiAgICAodm9pZClzd2FsbG93ezAsICgodm9pZClUOjphcHBseSh0KSwgMCkuLi59OwogIH0KfTsKdGVtcGxhdGUgPHR5cGVuYW1lIFQ+IHN0cnVjdCBtYWtlX3NvcnRpbmdfbmV0d29yayB7fTsKdGVtcGxhdGUgPHR5cGVuYW1lLi4uIFQ+IHN0cnVjdCBtYWtlX3NvcnRpbmdfbmV0d29yazxzdGQ6OnR1cGxlPFQuLi4+ID4geyB1c2luZyB0eXBlID0gc29ydGluZ19uZXR3b3JrPFQuLi4+OyB9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CnZvaWQgc29ydF90dXBsZShUJiYgdHVwbGUpIHsKICB1c2luZyBuZXR3b3JrID0gdHlwZW5hbWUgbWFrZV9zb3J0aW5nX25ldHdvcms8b2RkZXZlbjxzdGQ6OnR1cGxlX3NpemU8dHlwZW5hbWUgc3RkOjpkZWNheTxUPjo6dHlwZSA+Ojp2YWx1ZT4gPjo6dHlwZTsKICBuZXR3b3JrOjphcHBseShzdGQ6OmZvcndhcmQ8VD4odHVwbGUpKTsKfQoKdGVtcGxhdGUgPHR5cGVuYW1lLi4uIEFyZ3M+CnZvaWQgc29ydF9hcmd1bWVudHMoQXJncyYmLi4uIGFyZ3MpIHsKICBzb3J0X3R1cGxlKHN0ZDo6dGllKGFyZ3MuLi4pKTsKfQoKdGVtcGxhdGUgPHN0ZDo6c2l6ZV90IFM+CnVzaW5nIHN3YXBzX25lZWRlZCA9IHN0ZDo6dHVwbGVfc2l6ZTxvZGRldmVuPFM+ID47CgojaW5jbHVkZSA8aW9zdHJlYW0+CiNpbmNsdWRlIDxhcnJheT4KI2luY2x1ZGUgPHV0aWxpdHk+Cgp0ZW1wbGF0ZTxjbGFzcyBDaCwgY2xhc3MgVHIsIGNsYXNzIFR1cGxlLCBzdGQ6OnNpemVfdC4uLiBJcz4Kdm9pZCBwcmludF90dXBsZV9pbXBsKHN0ZDo6YmFzaWNfb3N0cmVhbTxDaCxUcj4mIG9zLAogICAgICAgICAgICAgICAgICAgICAgY29uc3QgVHVwbGUgJiB0LAogICAgICAgICAgICAgICAgICAgICAgc3RkOjppbmRleF9zZXF1ZW5jZTxJcy4uLj4pIHsKICAgIHVzaW5nIHN3YWxsb3cgPSBpbnRbXTsKICAgICh2b2lkKXN3YWxsb3d7MCwgKHZvaWQob3MgPDwgKElzID09IDA/ICIiIDogIiwgIikgPDwgc3RkOjpnZXQ8SXM+KHQpKSwgMCkuLi59Owp9Cgp0ZW1wbGF0ZTxjbGFzcyBDaCwgY2xhc3MgVHIsIGNsYXNzLi4uIEFyZ3M+CmRlY2x0eXBlKGF1dG8pIG9wZXJhdG9yPDwoc3RkOjpiYXNpY19vc3RyZWFtPENoLCBUcj4mIG9zLAogICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0ZDo6dHVwbGU8QXJncy4uLj4mIHQpIHsKICAgIG9zIDw8ICIoIjsKICAgIHByaW50X3R1cGxlX2ltcGwob3MsIHQsIHN0ZDo6aW5kZXhfc2VxdWVuY2VfZm9yPEFyZ3MuLi4+e30pOwogICAgcmV0dXJuIG9zIDw8ICIpIjsKfQoKaW50IG1haW4oKQp7CiAgYXV0byB0ID0gc3RkOjptYWtlX3R1cGxlKDIsIDQsIDMsIDUsIDksIDYsIDEsIDcsIDgpOwogIHNvcnRfdHVwbGUodCk7CiAgc3RkOjpjb3V0IDw8ICJzb3J0ZWQgaW4gIgogICAgICAgICAgICA8PCBzd2Fwc19uZWVkZWQ8c3RkOjp0dXBsZV9zaXplPGRlY2x0eXBlKHQpPjo6dmFsdWU+Ojp2YWx1ZQogICAgICAgICAgICA8PCAiIHN0ZXBzOiAiCiAgICAgICAgICAgIDw8IHQgPDwgJ1xuJzsKfQo=