#pragma GCC system_header

#ifndef _LIBCXX_ITERATOR
#define _LIBCXX_ITERATOR

#include <__config>
#include <stddef.h>
#include <type_traits>

_LIBCXX_BEGIN_NAMESPACE_STD

struct input_iterator_tag {
};
struct output_iterator_tag {
};
struct forward_iterator_tag : public input_iterator_tag {
};
struct bidirectional_iterator_tag : public forward_iterator_tag {
};
struct random_access_iterator_tag : public bidirectional_iterator_tag {
};

template <class Iter>
struct iterator_traits {
    using value_type = typename Iter::value_type;
    using difference_type = typename Iter::difference_type;
    using pointer = typename Iter::pointer;
    using reference = typename Iter::reference;
    using iterator_category = typename Iter::iterator_category;
};

template <class T>
struct iterator_traits<T*> {
    using value_type = T;
    using difference_type = ptrdiff_t;
    using pointer = T*;
    using reference = T&;
    using iterator_category = std::random_access_iterator_tag;
};

template <class T>
class __legacy_iter {
};

template <class T>
class __legacy_iter<T*> {
public:
    using value_type = T;
    using difference_type = ptrdiff_t;
    using pointer = T*;
    using reference = T&;
    using iterator_category = std::random_access_iterator_tag;

    __legacy_iter() = default;
    __legacy_iter(pointer p)
        : m_p(p)
    {
    }

    ~__legacy_iter() = default;

    bool operator!=(const __legacy_iter& other) const { return m_p != other.m_p; }
    bool operator==(const __legacy_iter& other) const { return m_p == other.m_p; }
    bool operator<(const __legacy_iter& other) const { return m_p < other.m_p; }
    bool operator>(const __legacy_iter& other) const { return m_p > other.m_p; }
    bool operator>=(const __legacy_iter& other) const { return m_p >= other.m_p; }

    __legacy_iter& operator++()
    {
        ++m_p;
        return *this;
    }

    __legacy_iter& operator--()
    {
        --m_p;
        return *this;
    }

    __legacy_iter operator++(int)
    {
        auto tmp = *this;
        ++m_p;
        return tmp;
    }

    __legacy_iter operator--(int)
    {
        auto tmp = *this;
        --m_p;
        return tmp;
    }

    __legacy_iter operator-(difference_type value) { return { m_p - value }; }
    __legacy_iter operator+(difference_type value) { return { m_p + value }; }

    __legacy_iter& operator+=(difference_type value)
    {
        m_p += value;
        return *this;
    }

    __legacy_iter& operator-=(difference_type value)
    {
        m_p -= value;
        return *this;
    }

    __legacy_iter& operator=(const __legacy_iter& other)
    {
        m_p = other.m_p;
        return *this;
    }
    reference operator*() { return *m_p; }
    difference_type operator-(const __legacy_iter& other) { return m_p - other.m_p; }
    constexpr reference operator[](difference_type n) const { return m_p[n]; }

private:
    pointer m_p = nullptr;
};

template <class Iter>
class reverse_iterator {
public:
    using iterator_type = Iter;
    using value_type = typename Iter::value_type;
    using difference_type = typename Iter::difference_type;
    using pointer = typename Iter::pointer;
    using reference = typename Iter::reference;
    using iterator_category = typename Iter::iterator_category;

    constexpr reverse_iterator() = default;
    ~reverse_iterator() = default;

    constexpr explicit reverse_iterator(iterator_type base_iter)
        : m_base(base_iter)
    {
    }

    constexpr iterator_type base() const { return m_base; }

    bool operator!=(const reverse_iterator& other) const { return m_base != other.m_base; }
    bool operator==(const reverse_iterator& other) const { return m_base == other.m_base; }
    bool operator<(const reverse_iterator& other) const { return m_base < other.m_base; }
    bool operator>(const reverse_iterator& other) const { return m_base > other.m_base; }
    bool operator>=(const reverse_iterator& other) const { return m_base >= other.m_base; }

    reverse_iterator& operator++()
    {
        --m_base;
        return *this;
    }

    reverse_iterator& operator--()
    {
        ++m_base;
        return *this;
    }

    reverse_iterator operator++(int)
    {
        auto tmp = *this;
        --m_base;
        return tmp;
    }

    reverse_iterator operator--(int)
    {
        auto tmp = *this;
        ++m_base;
        return tmp;
    }

    reverse_iterator operator-(difference_type value) { return { m_base + value }; }
    reverse_iterator operator+(difference_type value) { return { m_base - value }; }

    reverse_iterator& operator+=(difference_type value)
    {
        m_base -= value;
        return *this;
    }

    reverse_iterator& operator-=(difference_type value)
    {
        m_base += value;
        return *this;
    }

    reverse_iterator& operator=(const reverse_iterator& other)
    {
        m_base = other.m_base;
        return *this;
    }

    reference operator*() { return *m_base; }
    difference_type operator-(const reverse_iterator& other) { return other.m_base - m_base; }
    constexpr reference operator[](difference_type n) const { return m_base[-n]; }

private:
    iterator_type m_base;
};

template <class Iter>
constexpr typename iterator_traits<Iter>::difference_type distance(Iter first, Iter last)
{
    typename iterator_traits<Iter>::difference_type res;
    while (first != last) {
        first++;
        res++;
    }
    return res;
};

template <class Iter, class Distance>
constexpr void advance(Iter& it, Distance n)
{
    if (n > 0) {
        while (n--) {
            it++;
        }
    } else if (n < 0) {
        while (n++) {
            it--;
        }
    }
}

_LIBCXX_END_NAMESPACE_STD

#endif // _LIBCXX_ITERATOR