#include namespace __DEBUG_UTIL__ { using namespace std; template concept is_iterable = requires(T &&x) { begin(x); } && !is_same_v, string>; void print(const char *x) { cerr << x; } void print(char x) { cerr << "\'" << x << "\'"; } void print(bool x) { cerr << (x ? "T" : "F"); } void print(string x) { cerr << "\"" << x << "\""; } void print(vector &v) { /* Overloaded this because stl optimizes vector by using _Bit_reference instead of bool to conserve space. */ int f = 0; cerr << '['; for (auto &&i : v) cerr << (f++ ? "," : "") << (i ? "T" : "F"); cerr << "]"; } template void print(T &&x) { if constexpr (is_iterable) if (size(x) && is_iterable) { /* Iterable inside Iterable */ int f = 0; cerr << "\n~~~~~\n"; for (auto &&i : x) { cerr << setw(2) << left << f++, print(i), cerr << "\n"; } cerr << "~~~~~\n"; } else { /* Normal Iterable */ int f = 0; cerr << "["; for (auto &&i : x) cerr << (f++ ? "," : ""), print(i); cerr << "]"; } else if constexpr (requires { x.pop(); }) /* Stacks, Priority Queues, Queues */ { auto temp = x; int f = 0; cerr << "["; if constexpr (requires { x.top(); }) while (!temp.empty()) cerr << (f++ ? "," : ""), print(temp.top()), temp.pop(); else while (!temp.empty()) cerr << (f++ ? "," : ""), print(temp.front()), temp.pop(); cerr << "]"; } else if constexpr (requires { x.first; x.second; }) /* Pair */ { cerr << '(', print(x.first), cerr << ',', print(x.second), cerr << ')'; } else if constexpr (requires { get<0>(x); }) /* Tuple */ { int f = 0; cerr << '(', apply([&f](auto... args) { ((cerr << (f++ ? "," : ""), print(args)), ...); }, x); cerr << ')'; } else cerr << x; } template void printer(const char *names, T &&head, V &&...tail) { int i = 0; for (size_t bracket = 0; names[i] != '\0' and (names[i] != ',' or bracket != 0); i++) if (names[i] == '(' or names[i] == '<' or names[i] == '{') bracket++; else if (names[i] == ')' or names[i] == '>' or names[i] == '}') bracket--; cerr.write(names, i) << " = "; print(head); if constexpr (sizeof...(tail)) cerr << " | ", printer(names + i + 1, tail...); else cerr << "\n"; } template void printerArr(const char *names, T arr[], size_t N, V... tail) { size_t i = 0; for (; names[i] and names[i] != ','; i++) cerr << names[i]; for (i++; names[i] and names[i] != ','; i++) ; cerr << " = ["; for (size_t ind = 0; ind < N; ind++) cerr << (ind ? "," : ""), print(arr[ind]); cerr << "]"; if constexpr (sizeof...(tail)) cerr << " | ", printerArr(names + i + 1, tail...); else cerr << "\n"; } } #define dbg(...) std::cerr << __LINE__ << ": ", __DEBUG_UTIL__::printer(#__VA_ARGS__, __VA_ARGS__) #define dbgArr(...) std::cerr << __LINE__ << ": ", __DEBUG_UTIL__::printerArr(#__VA_ARGS__, __VA_ARGS__)