penguin8331's Library

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub penguin8331/library

:warning: dump/dump.hpp

Code

#include <bits/stdc++.h>

#ifndef DEBUG_PRINT_HPP
#define DEBUG_PRINT_HPP
#define debug(...) debug_print::multi_print(#__VA_ARGS__, __VA_ARGS__)

#define INCLUDED(n) ((defined _GLIBCXX_##n) || (defined _LIBCPP_##n))

#if __cplusplus < 201703L
#warning Please use C++17 (or later version).
#endif
#if !INCLUDED(ALGORITHM)
#warning Please include <algorithm> before including debug_print.hpp.
#endif
#if !INCLUDED(CCTYPE)
#warning Please include <cctype> before including debug_print.hpp.
#endif
#if !INCLUDED(IOSTREAM)
#warning Please include <iostream> before including debug_print.hpp.
#endif
#if !INCLUDED(ITERATOR)
#warning Please include <iterator> before including debug_print.hpp.
#endif
#if !INCLUDED(STRING_VIEW)
#warning Please include <string_view> before including debug_print.hpp.
#endif
#if !INCLUDED(TYPE_TRAITS)
#warning Please include <type_traits> before including debug_print.hpp.
#endif

namespace debug_print
{
    std::ostream &os = std::cerr;

    template <class Tp>
    auto has_cbegin(int) -> decltype(std::cbegin(std::declval<Tp>()),
                                     std::true_type{});
    template <class Tp>
    auto has_cbegin(...) -> std::false_type;
    template <class Tp>
    auto has_value_type(int) -> decltype(std::declval<typename Tp::value_type>(),
                                         std::true_type{});
    template <class Tp>
    auto has_value_type(...) -> std::false_type;

    template <class Tp>
    [[maybe_unused]] constexpr bool is_iterable_container_v =
        decltype(has_cbegin<Tp>(int{}))::value;
    template <class Tp>
    [[maybe_unused]] constexpr bool is_container_v =
        decltype(has_value_type<Tp>(int{}))::value || is_iterable_container_v<Tp>;

    template <>
    [[maybe_unused]] constexpr bool is_iterable_container_v<std::string_view> =
        false;
    template <>
    [[maybe_unused]] constexpr bool is_container_v<std::string_view> = false;
#if INCLUDED(STRING)
    template <>
    [[maybe_unused]] constexpr bool is_iterable_container_v<std::string> = false;
    template <>
    [[maybe_unused]] constexpr bool is_container_v<std::string> = false;
#endif

    template <class Tp, class... Ts>
    struct first_element
    {
        using type = Tp;
    };
    template <class... Ts>
    using first_t = typename first_element<Ts...>::type;

    template <class Tp,
              std::enable_if_t<!decltype(has_value_type<Tp>(int{}))::value,
                               std::nullptr_t> = nullptr>
    auto check_elem(int) -> decltype(*std::cbegin(std::declval<Tp>()));
    template <class Tp, std::enable_if_t<decltype(has_value_type<Tp>(int{}))::value,
                                         std::nullptr_t> = nullptr>
    auto check_elem(int) -> typename Tp::value_type;
    template <class Tp>
    auto check_elem(...) -> void;

    template <class Tp>
    using elem_t = decltype(check_elem<Tp>(int{}));

    template <class Tp>
    [[maybe_unused]] constexpr bool is_multidim_container_v =
        is_container_v<Tp> && is_container_v<elem_t<Tp>>;

    template <class Tp>
    std::enable_if_t<!is_container_v<Tp>> out(const Tp &);
    void out(const char &);
    void out(const char *);
    void out(const std::string_view &);

#if INCLUDED(STRING)
    void out(const std::string &);
#endif

#ifdef __SIZEOF_INT128__
    void out(const __int128 &);
    void out(const unsigned __int128 &);
#endif

    template <class Tp1, class Tp2>
    void out(const std::pair<Tp1, Tp2> &);

#if INCLUDED(TUPLE)
    template <class... Ts>
    void out(const std::tuple<Ts...> &);
#endif

#if INCLUDED(STACK)
    template <class... Ts>
    void out(std::stack<Ts...>);
#endif

#if INCLUDED(QUEUE)
    template <class... Ts>
    void out(std::queue<Ts...>);
    template <class... Ts>
    void out(std::priority_queue<Ts...>);
#endif

    template <class C>
    std::enable_if_t<is_iterable_container_v<C>> out(const C &);

    template <class Tp>
    std::enable_if_t<!is_container_v<Tp>> out(const Tp &arg)
    {
        os << arg;
        return;
    }

    void out(const char &arg) { os << '\'' << arg << '\''; }

    void out(const char *arg) { os << '\"' << arg << '\"'; }

    void out(const std::string_view &arg) { os << '\"' << arg << '\"'; }

#if INCLUDED(STRING)
    void out(const std::string &arg) { os << '\"' << arg << '\"'; }
#endif

#ifdef __SIZEOF_INT128__
    void out(const __int128 &arg)
    {
        int sign = (arg < 0) ? (-1) : 1;
        if (sign == -1)
            os << '-';
        __int128 base = sign;
        while (sign * arg >= sign * base * 10)
            base *= 10;
        while (base)
        {
            os << static_cast<char>('0' + (arg / base % 10));
            base /= 10;
        }
    }

    void out(const unsigned __int128 &arg)
    {
        unsigned __int128 base = 1;
        while (arg >= base * 10)
            base *= 10;
        while (base)
        {
            os << static_cast<char>('0' + (arg / base % 10));
            base /= 10;
        }
    }
#endif

    template <class Tp1, class Tp2>
    void out(const std::pair<Tp1, Tp2> &arg)
    {
        os << '(';
        out(arg.first);
        os << ", ";
        out(arg.second);
        os << ')';
    }

#if INCLUDED(TUPLE)
    template <class T, std::size_t... Is>
    void print_tuple(const T &arg, std::index_sequence<Is...>)
    {
        static_cast<void>(
            ((os << (Is == 0 ? "" : ", "), out(std::get<Is>(arg))), ...));
    }

    template <class... Ts>
    void out(const std::tuple<Ts...> &arg)
    {
        os << '(';
        print_tuple(arg, std::make_index_sequence<sizeof...(Ts)>());
        os << ')';
    }
#endif

#if INCLUDED(STACK)
    template <class... Ts>
    void out(std::stack<Ts...> arg)
    {
        if (arg.empty())
        {
            os << "<empty stack>";
            return;
        }
        os << "[ ";
        while (!arg.empty())
        {
            out(arg.top());
            os << ' ';
            arg.pop();
        }
        os << ']';
    }
#endif

#if INCLUDED(QUEUE)
    template <class... Ts>
    void out(std::queue<Ts...> arg)
    {
        if (arg.empty())
        {
            os << "<empty queue>";
            return;
        }
        os << "[ ";
        while (!arg.empty())
        {
            out(arg.front());
            os << ' ';
            arg.pop();
        }
        os << ']';
    }
    template <class... Ts>
    void out(std::priority_queue<Ts...> arg)
    {
        if (arg.empty())
        {
            os << "<empty priority_queue>";
            return;
        }
        os << "[ ";
        while (!arg.empty())
        {
            out(arg.top());
            os << ' ';
            arg.pop();
        }
        os << ']';
    }
#endif

    template <class Container>
    std::enable_if_t<is_iterable_container_v<Container>> out(const Container &arg)
    {
        if (std::distance(std::cbegin(arg), std::cend(arg)) == 0)
        {
            os << "<empty container>";
            return;
        }
        os << "[ ";
        std::for_each(std::cbegin(arg), std::cend(arg),
                      [](const elem_t<Container> &elem)
                      {
                          out(elem);
                          os << ' ';
                      });
        os << ']';
        return;
    }

    template <class Tp>
    std::enable_if_t<!is_multidim_container_v<Tp>> print(
        const std::string_view &name, const Tp &arg)
    {
        os << name << ": ";
        out(arg);
        if constexpr (is_container_v<Tp>)
            os << '\n';
        return;
    }

    template <class Tp>
    std::enable_if_t<is_multidim_container_v<Tp>> print(std::string_view name,
                                                        const Tp &arg)
    {
        os << name << ": ";
        if (std::distance(std::cbegin(arg), std::cend(arg)) == 0)
        {
            os << "<empty multidimensional container>\n";
            return;
        }
        std::for_each(
            std::cbegin(arg), std::cend(arg),
            [&name, is_first_elem = true](const elem_t<Tp> &elem) mutable
            {
                if (is_first_elem)
                    is_first_elem = false;
                else
                    for (std::size_t i = 0; i < name.length() + 2; i++)
                        os << ' ';
                out(elem);
                os << '\n';
            });
        return;
    }

    template <class Tp, class... Ts>
    void multi_print(std::string_view names, const Tp &arg, const Ts &...args)
    {
        if constexpr (sizeof...(Ts) == 0)
        {
            names.remove_suffix(std::distance(
                names.crbegin(),
                std::find_if_not(names.crbegin(), names.crend(),
                                 [](const char c)
                                 { return std::isspace(c); })));
            print(names, arg);
            if constexpr (!is_container_v<Tp>)
                os << '\n';
        }
        else
        {
            std::size_t comma_pos = 0;

            for (std::size_t i = 0, paren_depth = 0, inside_quote = false;
                 i < names.length(); i++)
            {
                if (!inside_quote && paren_depth == 0 && i > 0 &&
                    names[i - 1] != '\'' && names[i] == ',')
                {
                    comma_pos = i;
                    break;
                }
                if (names[i] == '\"' || names[i] == '\'')
                {
                    if (i > 0 && names[i - 1] == '\\')
                        continue;
                    inside_quote ^= true;
                }
                if (!inside_quote && names[i] == '(' &&
                    (i == 0 || names[i - 1] != '\''))
                    paren_depth++;
                if (!inside_quote && names[i] == ')' &&
                    (i == 0 || names[i - 1] != '\''))
                    paren_depth--;
            }

            const std::size_t first_varname_length =
                comma_pos -
                std::distance(
                    names.crend() - comma_pos,
                    std::find_if_not(names.crend() - comma_pos, names.crend(),
                                     [](const char c)
                                     { return std::isspace(c); }));
            print(names.substr(0, first_varname_length), arg);

            if constexpr (!is_container_v<Tp>)
            {
                if constexpr (is_container_v<first_t<Ts...>>)
                    os << '\n';
                else
                    os << " | ";
            }

            const std::size_t next_varname_begins_at = std::distance(
                names.cbegin(),
                std::find_if_not(names.cbegin() + comma_pos + 1, names.cend(),
                                 [](const char c)
                                 { return std::isspace(c); }));
            names.remove_prefix(next_varname_begins_at);

            multi_print(names, args...);
        }
    }
} // namespace debug_print

#undef INCLUDED

#endif // DEBUG_PRINT_HPP
#line 1 "dump/dump.hpp"
#include <bits/stdc++.h>

#ifndef DEBUG_PRINT_HPP
#define DEBUG_PRINT_HPP
#define debug(...) debug_print::multi_print(#__VA_ARGS__, __VA_ARGS__)

#define INCLUDED(n) ((defined _GLIBCXX_##n) || (defined _LIBCPP_##n))

#if __cplusplus < 201703L
#warning Please use C++17 (or later version).
#endif
#if !INCLUDED(ALGORITHM)
#warning Please include <algorithm> before including debug_print.hpp.
#endif
#if !INCLUDED(CCTYPE)
#warning Please include <cctype> before including debug_print.hpp.
#endif
#if !INCLUDED(IOSTREAM)
#warning Please include <iostream> before including debug_print.hpp.
#endif
#if !INCLUDED(ITERATOR)
#warning Please include <iterator> before including debug_print.hpp.
#endif
#if !INCLUDED(STRING_VIEW)
#warning Please include <string_view> before including debug_print.hpp.
#endif
#if !INCLUDED(TYPE_TRAITS)
#warning Please include <type_traits> before including debug_print.hpp.
#endif

namespace debug_print
{
    std::ostream &os = std::cerr;

    template <class Tp>
    auto has_cbegin(int) -> decltype(std::cbegin(std::declval<Tp>()),
                                     std::true_type{});
    template <class Tp>
    auto has_cbegin(...) -> std::false_type;
    template <class Tp>
    auto has_value_type(int) -> decltype(std::declval<typename Tp::value_type>(),
                                         std::true_type{});
    template <class Tp>
    auto has_value_type(...) -> std::false_type;

    template <class Tp>
    [[maybe_unused]] constexpr bool is_iterable_container_v =
        decltype(has_cbegin<Tp>(int{}))::value;
    template <class Tp>
    [[maybe_unused]] constexpr bool is_container_v =
        decltype(has_value_type<Tp>(int{}))::value || is_iterable_container_v<Tp>;

    template <>
    [[maybe_unused]] constexpr bool is_iterable_container_v<std::string_view> =
        false;
    template <>
    [[maybe_unused]] constexpr bool is_container_v<std::string_view> = false;
#if INCLUDED(STRING)
    template <>
    [[maybe_unused]] constexpr bool is_iterable_container_v<std::string> = false;
    template <>
    [[maybe_unused]] constexpr bool is_container_v<std::string> = false;
#endif

    template <class Tp, class... Ts>
    struct first_element
    {
        using type = Tp;
    };
    template <class... Ts>
    using first_t = typename first_element<Ts...>::type;

    template <class Tp,
              std::enable_if_t<!decltype(has_value_type<Tp>(int{}))::value,
                               std::nullptr_t> = nullptr>
    auto check_elem(int) -> decltype(*std::cbegin(std::declval<Tp>()));
    template <class Tp, std::enable_if_t<decltype(has_value_type<Tp>(int{}))::value,
                                         std::nullptr_t> = nullptr>
    auto check_elem(int) -> typename Tp::value_type;
    template <class Tp>
    auto check_elem(...) -> void;

    template <class Tp>
    using elem_t = decltype(check_elem<Tp>(int{}));

    template <class Tp>
    [[maybe_unused]] constexpr bool is_multidim_container_v =
        is_container_v<Tp> && is_container_v<elem_t<Tp>>;

    template <class Tp>
    std::enable_if_t<!is_container_v<Tp>> out(const Tp &);
    void out(const char &);
    void out(const char *);
    void out(const std::string_view &);

#if INCLUDED(STRING)
    void out(const std::string &);
#endif

#ifdef __SIZEOF_INT128__
    void out(const __int128 &);
    void out(const unsigned __int128 &);
#endif

    template <class Tp1, class Tp2>
    void out(const std::pair<Tp1, Tp2> &);

#if INCLUDED(TUPLE)
    template <class... Ts>
    void out(const std::tuple<Ts...> &);
#endif

#if INCLUDED(STACK)
    template <class... Ts>
    void out(std::stack<Ts...>);
#endif

#if INCLUDED(QUEUE)
    template <class... Ts>
    void out(std::queue<Ts...>);
    template <class... Ts>
    void out(std::priority_queue<Ts...>);
#endif

    template <class C>
    std::enable_if_t<is_iterable_container_v<C>> out(const C &);

    template <class Tp>
    std::enable_if_t<!is_container_v<Tp>> out(const Tp &arg)
    {
        os << arg;
        return;
    }

    void out(const char &arg) { os << '\'' << arg << '\''; }

    void out(const char *arg) { os << '\"' << arg << '\"'; }

    void out(const std::string_view &arg) { os << '\"' << arg << '\"'; }

#if INCLUDED(STRING)
    void out(const std::string &arg) { os << '\"' << arg << '\"'; }
#endif

#ifdef __SIZEOF_INT128__
    void out(const __int128 &arg)
    {
        int sign = (arg < 0) ? (-1) : 1;
        if (sign == -1)
            os << '-';
        __int128 base = sign;
        while (sign * arg >= sign * base * 10)
            base *= 10;
        while (base)
        {
            os << static_cast<char>('0' + (arg / base % 10));
            base /= 10;
        }
    }

    void out(const unsigned __int128 &arg)
    {
        unsigned __int128 base = 1;
        while (arg >= base * 10)
            base *= 10;
        while (base)
        {
            os << static_cast<char>('0' + (arg / base % 10));
            base /= 10;
        }
    }
#endif

    template <class Tp1, class Tp2>
    void out(const std::pair<Tp1, Tp2> &arg)
    {
        os << '(';
        out(arg.first);
        os << ", ";
        out(arg.second);
        os << ')';
    }

#if INCLUDED(TUPLE)
    template <class T, std::size_t... Is>
    void print_tuple(const T &arg, std::index_sequence<Is...>)
    {
        static_cast<void>(
            ((os << (Is == 0 ? "" : ", "), out(std::get<Is>(arg))), ...));
    }

    template <class... Ts>
    void out(const std::tuple<Ts...> &arg)
    {
        os << '(';
        print_tuple(arg, std::make_index_sequence<sizeof...(Ts)>());
        os << ')';
    }
#endif

#if INCLUDED(STACK)
    template <class... Ts>
    void out(std::stack<Ts...> arg)
    {
        if (arg.empty())
        {
            os << "<empty stack>";
            return;
        }
        os << "[ ";
        while (!arg.empty())
        {
            out(arg.top());
            os << ' ';
            arg.pop();
        }
        os << ']';
    }
#endif

#if INCLUDED(QUEUE)
    template <class... Ts>
    void out(std::queue<Ts...> arg)
    {
        if (arg.empty())
        {
            os << "<empty queue>";
            return;
        }
        os << "[ ";
        while (!arg.empty())
        {
            out(arg.front());
            os << ' ';
            arg.pop();
        }
        os << ']';
    }
    template <class... Ts>
    void out(std::priority_queue<Ts...> arg)
    {
        if (arg.empty())
        {
            os << "<empty priority_queue>";
            return;
        }
        os << "[ ";
        while (!arg.empty())
        {
            out(arg.top());
            os << ' ';
            arg.pop();
        }
        os << ']';
    }
#endif

    template <class Container>
    std::enable_if_t<is_iterable_container_v<Container>> out(const Container &arg)
    {
        if (std::distance(std::cbegin(arg), std::cend(arg)) == 0)
        {
            os << "<empty container>";
            return;
        }
        os << "[ ";
        std::for_each(std::cbegin(arg), std::cend(arg),
                      [](const elem_t<Container> &elem)
                      {
                          out(elem);
                          os << ' ';
                      });
        os << ']';
        return;
    }

    template <class Tp>
    std::enable_if_t<!is_multidim_container_v<Tp>> print(
        const std::string_view &name, const Tp &arg)
    {
        os << name << ": ";
        out(arg);
        if constexpr (is_container_v<Tp>)
            os << '\n';
        return;
    }

    template <class Tp>
    std::enable_if_t<is_multidim_container_v<Tp>> print(std::string_view name,
                                                        const Tp &arg)
    {
        os << name << ": ";
        if (std::distance(std::cbegin(arg), std::cend(arg)) == 0)
        {
            os << "<empty multidimensional container>\n";
            return;
        }
        std::for_each(
            std::cbegin(arg), std::cend(arg),
            [&name, is_first_elem = true](const elem_t<Tp> &elem) mutable
            {
                if (is_first_elem)
                    is_first_elem = false;
                else
                    for (std::size_t i = 0; i < name.length() + 2; i++)
                        os << ' ';
                out(elem);
                os << '\n';
            });
        return;
    }

    template <class Tp, class... Ts>
    void multi_print(std::string_view names, const Tp &arg, const Ts &...args)
    {
        if constexpr (sizeof...(Ts) == 0)
        {
            names.remove_suffix(std::distance(
                names.crbegin(),
                std::find_if_not(names.crbegin(), names.crend(),
                                 [](const char c)
                                 { return std::isspace(c); })));
            print(names, arg);
            if constexpr (!is_container_v<Tp>)
                os << '\n';
        }
        else
        {
            std::size_t comma_pos = 0;

            for (std::size_t i = 0, paren_depth = 0, inside_quote = false;
                 i < names.length(); i++)
            {
                if (!inside_quote && paren_depth == 0 && i > 0 &&
                    names[i - 1] != '\'' && names[i] == ',')
                {
                    comma_pos = i;
                    break;
                }
                if (names[i] == '\"' || names[i] == '\'')
                {
                    if (i > 0 && names[i - 1] == '\\')
                        continue;
                    inside_quote ^= true;
                }
                if (!inside_quote && names[i] == '(' &&
                    (i == 0 || names[i - 1] != '\''))
                    paren_depth++;
                if (!inside_quote && names[i] == ')' &&
                    (i == 0 || names[i - 1] != '\''))
                    paren_depth--;
            }

            const std::size_t first_varname_length =
                comma_pos -
                std::distance(
                    names.crend() - comma_pos,
                    std::find_if_not(names.crend() - comma_pos, names.crend(),
                                     [](const char c)
                                     { return std::isspace(c); }));
            print(names.substr(0, first_varname_length), arg);

            if constexpr (!is_container_v<Tp>)
            {
                if constexpr (is_container_v<first_t<Ts...>>)
                    os << '\n';
                else
                    os << " | ";
            }

            const std::size_t next_varname_begins_at = std::distance(
                names.cbegin(),
                std::find_if_not(names.cbegin() + comma_pos + 1, names.cend(),
                                 [](const char c)
                                 { return std::isspace(c); }));
            names.remove_prefix(next_varname_begins_at);

            multi_print(names, args...);
        }
    }
} // namespace debug_print

#undef INCLUDED

#endif // DEBUG_PRINT_HPP
Back to top page