#include <iostream>
#pragma mark - Tape
constexpr int Blank = -1;
template<int... xs>
class Tape {
public:
using type = Tape<xs...>;
constexpr static int length = sizeof...(xs);
};
#pragma mark - Print
template<class T>
void print(T);
template<>
void print(Tape<>) {
std::cout << std::endl;
}
template<int x, int... xs>
void print(Tape<x, xs...>) {
if (x == Blank) {
std::cout << "_ ";
} else {
std::cout << x << " ";
}
print(Tape<xs...>());
}
#pragma mark - Concatenate
template<class, class>
class Concatenate;
template<int... xs, int... ys>
class Concatenate<Tape<xs...>, Tape<ys...>> {
public:
using type = Tape<xs..., ys...>;
};
#pragma mark - Invert
template<class>
class Invert;
template<>
class Invert<Tape<>> {
public:
using type = Tape<>;
};
template<int x, int... xs>
class Invert<Tape<x, xs...>> {
public:
using type = typename Concatenate<
typename Invert<Tape<xs...>>::type,
Tape<x>
>::type;
};
#pragma mark - Read
template<int, class>
class Read;
template<int n, int x, int... xs>
class Read<n, Tape<x, xs...>> {
public:
using type = typename std::conditional<
(n == 0),
std::integral_constant<int, x>,
Read<n - 1, Tape<xs...>>
>::type::type;
};
#pragma mark - N first and N last
template<int, class>
class NLast;
template<int n, int x, int... xs>
class NLast<n, Tape<x, xs...>> {
public:
using type = typename std::conditional<
(n == sizeof...(xs)),
Tape<xs...>,
NLast<n, Tape<xs...>>
>::type::type;
};
template<int, class>
class NFirst;
template<int n, int... xs>
class NFirst<n, Tape<xs...>> {
public:
using type = typename Invert<
typename NLast<
n, typename Invert<Tape<xs...>>::type
>::type
>::type;
};
#pragma mark - Write
template<int, int, class>
class Write;
template<int pos, int x, int... xs>
class Write<pos, x, Tape<xs...>> {
public:
using type = typename Concatenate<
typename Concatenate<
typename NFirst<pos, Tape<xs...>>::type,
Tape<x>
>::type,
typename NLast<(sizeof...(xs) - pos - 1), Tape<xs...>>::type
>::type;
};
#pragma mark - Move
template<int, class>
class Hold;
template<int pos, int... xs>
class Hold<pos, Tape<xs...>> {
public:
constexpr static int position = pos;
using tape = Tape<xs...>;
};
template<int, class>
class Left;
template<int pos, int... xs>
class Left<pos, Tape<xs...>> {
public:
constexpr static int position = typename std::conditional<
(pos > 0),
std::integral_constant<int, pos - 1>,
std::integral_constant<int, 0>
>::type();
using tape = typename std::conditional<
(pos > 0),
Tape<xs...>,
Tape<Blank, xs...>
>::type;
};
template<int, class>
class Right;
template<int pos, int... xs>
class Right<pos, Tape<xs...>> {
public:
constexpr static int position = pos + 1;
using tape = typename std::conditional<
(pos < sizeof...(xs) - 1),
Tape<xs...>,
Tape<xs..., Blank>
>::type;
};
int main() {
using tape = Tape<1, 2, 3, 4, 5>;
std::cout << Left<3, tape>::position << std::endl;
std::cout << Left<0, tape>::position << std::endl;
print(Left<0, tape>::tape());
std::cout << Right<3, tape>::position << std::endl;
std::cout << Right<4, tape>::position << std::endl;
print(Right<4, tape>::tape());
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgoKI3ByYWdtYSBtYXJrIC0gVGFwZQoKY29uc3RleHByIGludCBCbGFuayA9IC0xOwoKdGVtcGxhdGU8aW50Li4uIHhzPgpjbGFzcyBUYXBlIHsKcHVibGljOgogICAgdXNpbmcgdHlwZSA9IFRhcGU8eHMuLi4+OwogICAgY29uc3RleHByIHN0YXRpYyBpbnQgbGVuZ3RoID0gc2l6ZW9mLi4uKHhzKTsKfTsKCiNwcmFnbWEgbWFyayAtIFByaW50Cgp0ZW1wbGF0ZTxjbGFzcyBUPgp2b2lkIHByaW50KFQpOwoKdGVtcGxhdGU8Pgp2b2lkIHByaW50KFRhcGU8PikgewogICAgc3RkOjpjb3V0IDw8IHN0ZDo6ZW5kbDsKfQoKdGVtcGxhdGU8aW50IHgsIGludC4uLiB4cz4Kdm9pZCBwcmludChUYXBlPHgsIHhzLi4uPikgewogICAgaWYgKHggPT0gQmxhbmspIHsKICAgICAgICBzdGQ6OmNvdXQgPDwgIl8gIjsKICAgIH0gZWxzZSB7CiAgICAgICAgc3RkOjpjb3V0IDw8IHggPDwgIiAiOwogICAgfQogICAgcHJpbnQoVGFwZTx4cy4uLj4oKSk7Cn0KCiNwcmFnbWEgbWFyayAtIENvbmNhdGVuYXRlCgp0ZW1wbGF0ZTxjbGFzcywgY2xhc3M+CmNsYXNzIENvbmNhdGVuYXRlOwoKdGVtcGxhdGU8aW50Li4uIHhzLCBpbnQuLi4geXM+CmNsYXNzIENvbmNhdGVuYXRlPFRhcGU8eHMuLi4+LCBUYXBlPHlzLi4uPj4gewpwdWJsaWM6CiAgICB1c2luZyB0eXBlID0gVGFwZTx4cy4uLiwgeXMuLi4+Owp9OwoKI3ByYWdtYSBtYXJrIC0gSW52ZXJ0Cgp0ZW1wbGF0ZTxjbGFzcz4KY2xhc3MgSW52ZXJ0OwoKdGVtcGxhdGU8PgpjbGFzcyBJbnZlcnQ8VGFwZTw+PiB7CnB1YmxpYzoKICAgIHVzaW5nIHR5cGUgPSBUYXBlPD47Cn07Cgp0ZW1wbGF0ZTxpbnQgeCwgaW50Li4uIHhzPgpjbGFzcyBJbnZlcnQ8VGFwZTx4LCB4cy4uLj4+IHsKcHVibGljOgogICAgdXNpbmcgdHlwZSA9IHR5cGVuYW1lIENvbmNhdGVuYXRlPAogICAgICAgIHR5cGVuYW1lIEludmVydDxUYXBlPHhzLi4uPj46OnR5cGUsCiAgICAgICAgVGFwZTx4PgogICAgPjo6dHlwZTsKfTsKCiNwcmFnbWEgbWFyayAtIFJlYWQKCnRlbXBsYXRlPGludCwgY2xhc3M+CmNsYXNzIFJlYWQ7Cgp0ZW1wbGF0ZTxpbnQgbiwgaW50IHgsIGludC4uLiB4cz4KY2xhc3MgUmVhZDxuLCBUYXBlPHgsIHhzLi4uPj4gewpwdWJsaWM6CiAgICB1c2luZyB0eXBlID0gdHlwZW5hbWUgc3RkOjpjb25kaXRpb25hbDwKICAgICAgICAobiA9PSAwKSwKICAgICAgICBzdGQ6OmludGVncmFsX2NvbnN0YW50PGludCwgeD4sCiAgICAgICAgUmVhZDxuIC0gMSwgVGFwZTx4cy4uLj4+CiAgICA+Ojp0eXBlOjp0eXBlOwp9OwoKI3ByYWdtYSBtYXJrIC0gTiBmaXJzdCBhbmQgTiBsYXN0Cgp0ZW1wbGF0ZTxpbnQsIGNsYXNzPgpjbGFzcyBOTGFzdDsKCnRlbXBsYXRlPGludCBuLCBpbnQgeCwgaW50Li4uIHhzPgpjbGFzcyBOTGFzdDxuLCBUYXBlPHgsIHhzLi4uPj4gewpwdWJsaWM6CiAgICB1c2luZyB0eXBlID0gdHlwZW5hbWUgc3RkOjpjb25kaXRpb25hbDwKICAgICAgICAobiA9PSBzaXplb2YuLi4oeHMpKSwKICAgICAgICBUYXBlPHhzLi4uPiwKICAgICAgICBOTGFzdDxuLCBUYXBlPHhzLi4uPj4KICAgID46OnR5cGU6OnR5cGU7Cn07Cgp0ZW1wbGF0ZTxpbnQsIGNsYXNzPgpjbGFzcyBORmlyc3Q7Cgp0ZW1wbGF0ZTxpbnQgbiwgaW50Li4uIHhzPgpjbGFzcyBORmlyc3Q8biwgVGFwZTx4cy4uLj4+IHsKcHVibGljOgogICAgdXNpbmcgdHlwZSA9IHR5cGVuYW1lIEludmVydDwKICAgICAgICB0eXBlbmFtZSBOTGFzdDwKICAgICAgICAgICAgbiwgdHlwZW5hbWUgSW52ZXJ0PFRhcGU8eHMuLi4+Pjo6dHlwZQogICAgICAgID46OnR5cGUKICAgID46OnR5cGU7Cn07CgojcHJhZ21hIG1hcmsgLSBXcml0ZQoKdGVtcGxhdGU8aW50LCBpbnQsIGNsYXNzPgpjbGFzcyBXcml0ZTsKCnRlbXBsYXRlPGludCBwb3MsIGludCB4LCBpbnQuLi4geHM+CmNsYXNzIFdyaXRlPHBvcywgeCwgVGFwZTx4cy4uLj4+IHsKcHVibGljOgogICAgdXNpbmcgdHlwZSA9IHR5cGVuYW1lIENvbmNhdGVuYXRlPAogICAgICAgIHR5cGVuYW1lIENvbmNhdGVuYXRlPAogICAgICAgICAgICB0eXBlbmFtZSBORmlyc3Q8cG9zLCBUYXBlPHhzLi4uPj46OnR5cGUsCiAgICAgICAgICAgIFRhcGU8eD4KICAgICAgICA+Ojp0eXBlLAogICAgICAgIHR5cGVuYW1lIE5MYXN0PChzaXplb2YuLi4oeHMpIC0gcG9zIC0gMSksIFRhcGU8eHMuLi4+Pjo6dHlwZQogICAgPjo6dHlwZTsKfTsKCiNwcmFnbWEgbWFyayAtIE1vdmUKCnRlbXBsYXRlPGludCwgY2xhc3M+CmNsYXNzIEhvbGQ7Cgp0ZW1wbGF0ZTxpbnQgcG9zLCBpbnQuLi4geHM+CmNsYXNzIEhvbGQ8cG9zLCBUYXBlPHhzLi4uPj4gewpwdWJsaWM6CiAgICBjb25zdGV4cHIgc3RhdGljIGludCBwb3NpdGlvbiA9IHBvczsKICAgIHVzaW5nIHRhcGUgPSBUYXBlPHhzLi4uPjsKfTsKCnRlbXBsYXRlPGludCwgY2xhc3M+CmNsYXNzIExlZnQ7Cgp0ZW1wbGF0ZTxpbnQgcG9zLCBpbnQuLi4geHM+CmNsYXNzIExlZnQ8cG9zLCBUYXBlPHhzLi4uPj4gewpwdWJsaWM6CiAgICBjb25zdGV4cHIgc3RhdGljIGludCBwb3NpdGlvbiA9IHR5cGVuYW1lIHN0ZDo6Y29uZGl0aW9uYWw8CiAgICAgICAgKHBvcyA+IDApLAogICAgICAgIHN0ZDo6aW50ZWdyYWxfY29uc3RhbnQ8aW50LCBwb3MgLSAxPiwKICAgICAgICBzdGQ6OmludGVncmFsX2NvbnN0YW50PGludCwgMD4KICAgID46OnR5cGUoKTsKCiAgICB1c2luZyB0YXBlID0gdHlwZW5hbWUgc3RkOjpjb25kaXRpb25hbDwKICAgICAgICAocG9zID4gMCksCiAgICAgICAgVGFwZTx4cy4uLj4sCiAgICAgICAgVGFwZTxCbGFuaywgeHMuLi4+CiAgICA+Ojp0eXBlOwp9OwoKdGVtcGxhdGU8aW50LCBjbGFzcz4KY2xhc3MgUmlnaHQ7Cgp0ZW1wbGF0ZTxpbnQgcG9zLCBpbnQuLi4geHM+CmNsYXNzIFJpZ2h0PHBvcywgVGFwZTx4cy4uLj4+IHsKcHVibGljOgogICAgY29uc3RleHByIHN0YXRpYyBpbnQgcG9zaXRpb24gPSBwb3MgKyAxOwoKICAgIHVzaW5nIHRhcGUgPSB0eXBlbmFtZSBzdGQ6OmNvbmRpdGlvbmFsPAogICAgICAgIChwb3MgPCBzaXplb2YuLi4oeHMpIC0gMSksCiAgICAgICAgVGFwZTx4cy4uLj4sCiAgICAgICAgVGFwZTx4cy4uLiwgQmxhbms+CiAgICA+Ojp0eXBlOwp9OwoKaW50IG1haW4oKSB7Cgl1c2luZyB0YXBlID0gVGFwZTwxLCAyLCAzLCA0LCA1PjsKCQoJc3RkOjpjb3V0IDw8IExlZnQ8MywgdGFwZT46OnBvc2l0aW9uIDw8IHN0ZDo6ZW5kbDsKCXN0ZDo6Y291dCA8PCBMZWZ0PDAsIHRhcGU+Ojpwb3NpdGlvbiA8PCBzdGQ6OmVuZGw7CglwcmludChMZWZ0PDAsIHRhcGU+Ojp0YXBlKCkpOwoJCglzdGQ6OmNvdXQgPDwgUmlnaHQ8MywgdGFwZT46OnBvc2l0aW9uIDw8IHN0ZDo6ZW5kbDsKCXN0ZDo6Y291dCA8PCBSaWdodDw0LCB0YXBlPjo6cG9zaXRpb24gPDwgc3RkOjplbmRsOwoJcHJpbnQoUmlnaHQ8NCwgdGFwZT46OnRhcGUoKSk7CgkKCXJldHVybiAwOwp9