Created
June 20, 2020 15:29
-
-
Save qookei/cfee4fdb5ec33be5cede1bf364690d59 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* compile with: g++ gorbitsa.cpp -o gorbitsa -ftemplate-depth=99999999 -std=c++2a | |
* Tested with GCC 10.1, does *not* work with Clang 10 | |
*/ | |
#include <iostream> | |
#include <string_view> | |
#include <cctype> | |
#include <array> | |
#include <type_traits> | |
#include <tuple> | |
// From https://github.com/managarm/frigg/blob/master/include/frg/array.hpp, lines 92-124 | |
// s/frg::/std::/ | |
namespace details { | |
template<typename ...Ts> | |
struct concat_size; | |
template<typename ...Ts> | |
inline constexpr size_t concat_size_v = concat_size<Ts...>::value; | |
template<typename T, typename ...Ts> | |
struct concat_size<T, Ts...> | |
: std::integral_constant<size_t, std::tuple_size_v<T> + concat_size_v<Ts...>> { }; | |
template<> | |
struct concat_size<> | |
: std::integral_constant<size_t, 0> { }; | |
template<typename X, size_t N> | |
constexpr void concat_insert(std::array<X, N> &, size_t) { } | |
template<typename X, size_t N, typename T, typename... Ts> | |
constexpr void concat_insert(std::array<X, N> &res, size_t at, const T &other, const Ts &...tail) { | |
size_t n = std::tuple_size_v<T>; | |
for(size_t i = 0; i < n; ++i) | |
res[at + i] = other[i]; | |
concat_insert(res, at + n, tail...); | |
} | |
} // namespace details | |
template<typename X, typename ...Ts> | |
constexpr auto array_concat(const Ts &...arrays) { | |
std::array<X, details::concat_size_v<Ts...>> res{}; | |
details::concat_insert(res, 0, arrays...); | |
return res; | |
} | |
template <size_t I> | |
constexpr auto set(auto a, auto b) { | |
a[I] = b; | |
return a; | |
} | |
template <size_t PC, uint8_t X, size_t I, std::array<uint8_t, 256> Ram, uint8_t ...Ts> | |
constexpr auto run_impl(std::array<uint8_t, I> out) { | |
if constexpr (PC >= sizeof...(Ts)) | |
return out; | |
else { | |
constexpr uint8_t op = std::get<PC>(std::make_tuple(Ts...)); | |
constexpr uint8_t arg = std::get<PC + 1>(std::make_tuple(Ts...)); | |
if constexpr (op == 'G') | |
return run_impl<PC + 2, Ram[arg], out.size(), Ram, Ts...>(out); | |
else if constexpr (op == 'O') | |
return run_impl<PC + 2, X, out.size(), set<arg>(Ram, X), Ts...>(out); | |
else if constexpr (op == 'R') | |
return run_impl<PC + 2, /*input*/ 0, out.size(), Ram, Ts...>(out); | |
else if constexpr (op == 'B') | |
return run_impl<X ? PC + 2 : arg * 2, X, out.size(), Ram, Ts...>(out); | |
else if constexpr (op == 'I') | |
return run_impl<PC + 2, (X + arg) & 0xFF, out.size(), Ram, Ts...>(out); | |
else if constexpr (op == 'T') | |
return run_impl<PC + 2, X, out.size() + 1, Ram, Ts...>( | |
array_concat<uint8_t>(out, std::array<uint8_t, 1>{X})); | |
else if constexpr (op == 'S') | |
return run_impl<PC + 2, arg, out.size(), Ram, Ts...>(out); | |
else if constexpr (op == 'A') | |
return run_impl<PC + 2, (X + Ram[arg]) & 0xFF, out.size(), Ram, Ts...>(out); | |
else if constexpr (op == 'g') | |
return run_impl<PC + 2, Ram[Ram[arg]], out.size(), Ram, Ts...>(out); | |
else if constexpr (op == 'o') | |
return run_impl<PC + 2, X, out.size(), set<Ram[arg]>(Ram, X), Ts...>(out); | |
else if constexpr (op == 'r') | |
return run_impl<PC + 2, X, out.size(), set<arg>(Ram, /*input*/ 0), Ts...>(out); | |
else if constexpr (op == 'b') | |
return run_impl<X ? PC + 2 : Ram[arg] * 2, X, out.size(), Ram, Ts...>(out); | |
else if constexpr (op == 'i') | |
return run_impl<PC + 2, X, out.size(), set<arg>(Ram, (Ram[arg] + X) & 0xFF), Ts...>(out); | |
else if constexpr (op == 't') | |
return run_impl<PC + 2, X, out.size() + 1, Ram, Ts...>( | |
array_concat<uint8_t>(out, std::array<uint8_t, 1>{Ram[arg]})); | |
else if constexpr (op == 's') | |
return run_impl<PC + 2, X ^ Ram[arg], out.size(), Ram, Ts...>(out); | |
else if constexpr (op == 'a') | |
return run_impl<PC + 2, (X + Ram[Ram[arg]]) & 0xFF, out.size(), Ram, Ts...>(out); | |
else | |
return std::array<uint8_t, 9>{'E', 'r', 'r', 'o', 'r', 'O', op, 'A', arg}; | |
} | |
} | |
template <uint8_t ...c> | |
constexpr auto run() { | |
return run_impl<0, 0, 0, std::array<uint8_t, 256>{}, c...>({}); | |
} | |
int main() { | |
// Hello | |
auto output = run<'S', 72, 'T', 0, 'S', 101, 'T', 0, 'S', 108, 'T', 0, 'T', 0, 'S', 111, 'T', 0>(); | |
// A 10x10 Box (By Megarev) | |
//auto output = run<'S', 10, 'O', 0, 'G', 0, 'I', 255, 'O', 0, 'B', 19, 'S', 10, 'T', 0, 'S', 10, 'O', 1, 'G', 1, 'I', 255, 'O', 1, 'S', 35, 'T', 0, 'G', 1, 'B', 2, 'S', 0, 'B', 10, 'S', 10, 'T', 0>(); | |
// Sauron's eye (By TrolledWoods) (Broken) | |
//auto output = run<'S', 206, 'O', 132, 'S', 10, 'T', 0, 'S', 156, 'O', 97, 'S', 1, 'i', 97, 'S', 0, 'O', 7, 'G', 97, 'I', 237, 'O', 131, 'G', 97, 'i', 7, 'S', 1, 'i', 131, 'G', 131, 'B', 42, 'S', 0, 'B', 26, 'S', 0, 'O', 105, 'G', 132, 'I', 45, 'O', 131, 'G', 132, 'i', 105, 'S', 1, 'i', 131, 'G', 131, 'B', 68, 'S', 0, 'B', 52, 'G', 105, 'i', 7, 'S', 200, 'O', 105, 'G', 7, 'B', 94, 'G', 105, 'B', 102, 'S', 255, 'i', 7, 'i', 105, 'S', 0, 'B', 76, 'S', 46, 'T', 0, 'S', 0, 'B', 110, 'S', 35, 'T', 0, 'S', 0, 'B', 110, 'G', 97, 'B', 118, 'S', 0, 'B', 12, 'S', 1, 'i', 132, 'G', 132, 'B', 255, 'S', 0, 'B', 4>(); | |
for (auto c : output) | |
std::putchar(c); | |
std::putchar('\n'); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment