Skip to content

Instantly share code, notes, and snippets.

@qookei
Created June 20, 2020 15:29
Show Gist options
  • Save qookei/cfee4fdb5ec33be5cede1bf364690d59 to your computer and use it in GitHub Desktop.
Save qookei/cfee4fdb5ec33be5cede1bf364690d59 to your computer and use it in GitHub Desktop.
/*
* 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