#include "./other/type-utils.hpp"
/*
- Streamable(string含む) -> そのまま出力
- is_modint(.val()->int) -> .val()して出力
以下のものは順に再帰的に出力する
- pair,tuple
- ranges::begin(),ranges::end()が使える型(vector,deque,set,map,....)
*/
template <class... Args> void debug_print(const std::tuple<Args...> &);
template <std::ranges::range Iterable>
requires(!Streamable<Iterable>)
void debug_print(const Iterable &);
template <Streamable T> void debug_print(const T &value) { std::cerr << value; }
template <is_modint mint>
requires(!Streamable<mint>)
void debug_print(const mint &value) {
std::cerr << value.val();
}
template <class F, class S> void debug_print(const std::pair<F, S> &value) {
std::cerr << "[";
debug_print(value.first);
std::cerr << ", ";
debug_print(value.second);
std::cerr << "]";
}
template <size_t N = 0, class T> void enum_tuple(const T &value) {
if constexpr(N < std::tuple_size<T>::value) {
const auto &x = get<N>(value);
debug_print(x);
if(N + 1 < std::tuple_size<T>::value) {
std::cerr << ", ";
enum_tuple<N + 1, T>(value);
}
}
}
template <class... Args> void debug_print(const std::tuple<Args...> &value) {
std::cerr << "[";
enum_tuple(value);
std::cerr << "]";
}
template <std::ranges::range Iterable>
requires(!Streamable<Iterable>)
void debug_print(const Iterable &v) {
std::cerr << "[";
for(auto itr = std::ranges::begin(v); itr != std::ranges::end(v); itr++) {
if(itr != std::ranges::begin(v))
std::cerr << ", ";
debug_print(*itr);
}
std::cerr << "]";
}
#include <boost/preprocessor.hpp>
#define DEBUG_PRINT_VAR_I(r, data, i, elem) \
std::cerr << BOOST_PP_STRINGIZE(elem) << ": "; \
debug_print(elem); \
std::cerr << BOOST_PP_IF( \
BOOST_PP_NOT_EQUAL(i, BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(data))), ", ", \
"");
#define debug(...) \
do { \
BOOST_PP_SEQ_FOR_EACH_I(DEBUG_PRINT_VAR_I, \
BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__), \
BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) \
std::cerr << std::endl; \
} while(0)
#line 2 "other/type-utils.hpp"
#include <bits/stdc++.h>
using ll = long long;
using u32 = unsigned int;
using u64 = unsigned long long;
using i128 = __int128;
using u128 = unsigned __int128;
using vi = std::vector<int>;
using vii = std::vector<std::vector<int>>;
using pii = std::pair<int, int>;
using vl = std::vector<ll>;
using vll = std::vector<vl>;
using pll = std::pair<ll, ll>;
template <class T>
concept extended_integral =
std::integral<T> || std::same_as<std::remove_cv_t<T>, i128> ||
std::same_as<std::remove_cv_t<T>, u128>;
template <class T>
concept extended_signed_integral =
std::signed_integral<T> || std::same_as<std::remove_cv_t<T>, i128>;
template <class T>
concept extended_unsigned_integral =
std::unsigned_integral<T> || std::same_as<std::remove_cv_t<T>, u128>;
template <class T>
concept Streamable =
requires(std::ostream &os, T &x) { os << x; } || extended_integral<T>;
template <class mint>
concept is_modint = requires(mint &x) {
{ x.val() } -> std::convertible_to<int>;
};
#line 2 "debug.hpp"
/*
- Streamable(string含む) -> そのまま出力
- is_modint(.val()->int) -> .val()して出力
以下のものは順に再帰的に出力する
- pair,tuple
- ranges::begin(),ranges::end()が使える型(vector,deque,set,map,....)
*/
template <class... Args> void debug_print(const std::tuple<Args...> &);
template <std::ranges::range Iterable>
requires(!Streamable<Iterable>)
void debug_print(const Iterable &);
template <Streamable T> void debug_print(const T &value) { std::cerr << value; }
template <is_modint mint>
requires(!Streamable<mint>)
void debug_print(const mint &value) {
std::cerr << value.val();
}
template <class F, class S> void debug_print(const std::pair<F, S> &value) {
std::cerr << "[";
debug_print(value.first);
std::cerr << ", ";
debug_print(value.second);
std::cerr << "]";
}
template <size_t N = 0, class T> void enum_tuple(const T &value) {
if constexpr(N < std::tuple_size<T>::value) {
const auto &x = get<N>(value);
debug_print(x);
if(N + 1 < std::tuple_size<T>::value) {
std::cerr << ", ";
enum_tuple<N + 1, T>(value);
}
}
}
template <class... Args> void debug_print(const std::tuple<Args...> &value) {
std::cerr << "[";
enum_tuple(value);
std::cerr << "]";
}
template <std::ranges::range Iterable>
requires(!Streamable<Iterable>)
void debug_print(const Iterable &v) {
std::cerr << "[";
for(auto itr = std::ranges::begin(v); itr != std::ranges::end(v); itr++) {
if(itr != std::ranges::begin(v))
std::cerr << ", ";
debug_print(*itr);
}
std::cerr << "]";
}
#include <boost/preprocessor.hpp>
#define DEBUG_PRINT_VAR_I(r, data, i, elem) \
std::cerr << BOOST_PP_STRINGIZE(elem) << ": "; \
debug_print(elem); \
std::cerr << BOOST_PP_IF( \
BOOST_PP_NOT_EQUAL(i, BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(data))), ", ", \
"");
#define debug(...) \
do { \
BOOST_PP_SEQ_FOR_EACH_I(DEBUG_PRINT_VAR_I, \
BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__), \
BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) \
std::cerr << std::endl; \
} while(0)