This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub suisen-cp/cp-library-cpp
#include "library/util/zobrist_hash.hpp"
#ifndef SUISEN_ZOBRIST_HASH #define SUISEN_ZOBRIST_HASH #include <algorithm> #include <array> #include <map> #include <vector> #include <random> namespace suisen { template <typename ContainerType, typename ValueType, typename HashType, typename Derived> struct ZobristHashBase { using container_type = ContainerType; using value_type = ValueType; using hash_type = std::make_unsigned_t<HashType>; using rng_type = std::mt19937_64; using self_type = Derived; template <typename ...Args> ZobristHashBase(Args &&...args) : rng(std::random_device{}()), h(std::forward<Args>(args)...) {} hash_type operator()(const value_type &val) { Self::ensure_key_existence(h, val, rng); return h[val]; } hash_type empty_set() const { return 0; } hash_type sigleton_set(const value_type& val) { return (*this)(val); } hash_type flip(hash_type old_hash, const value_type& val) { return old_hash ^ (*this)(val); } hash_type xor_set(hash_type set1, hash_type set2) const { return set1 ^ set2; } protected: rng_type rng; container_type h; private: struct Self : public self_type { using self_type::ensure_key_existence; }; }; template <typename HashType = std::uint64_t, std::enable_if_t<std::is_integral_v<HashType>, std::nullptr_t> = nullptr> struct VecZobristHash : public ZobristHashBase<std::vector<std::make_unsigned_t<HashType>>, std::size_t, HashType, VecZobristHash<HashType>> { using Base = ZobristHashBase<std::vector<std::make_unsigned_t<HashType>>, std::size_t, HashType, VecZobristHash<HashType>>; VecZobristHash() = default; VecZobristHash(typename Base::value_type max_val) : Base(max_val + 1) { std::generate(this->h.begin(), this->h.end(), this->rng); } protected: static void ensure_key_existence(typename Base::container_type& h, typename Base::value_type v, typename Base::rng_type& rng) { if (std::size_t old_size = h.size(); old_size <= v) { h.resize(v + 1); for (std::size_t i = old_size; i <= v; ++i) h[i] = rng(); } } }; template <std::size_t N, typename HashType = std::uint64_t, std::enable_if_t<std::is_integral_v<HashType>, std::nullptr_t> = nullptr> struct ArrZobristHash : public ZobristHashBase<std::array<std::make_unsigned_t<HashType>, N + 1>, std::size_t, HashType, ArrZobristHash<N, HashType>> { using Base = ZobristHashBase<std::array<std::make_unsigned_t<HashType>, N + 1>, std::size_t, HashType, ArrZobristHash<N, HashType>>; ArrZobristHash() { std::generate(this->h.begin(), this->h.end(), this->rng); } protected: static void ensure_key_existence(typename Base::container_type&, typename Base::value_type, typename Base::rng_type&) {} }; template <typename ValueType, typename HashType = std::uint64_t, std::enable_if_t<std::is_integral_v<HashType>, std::nullptr_t> = nullptr> struct MapZobristHash : public ZobristHashBase<std::map<ValueType, std::make_unsigned_t<HashType>>, ValueType, HashType, MapZobristHash<ValueType, HashType>> { using Base = ZobristHashBase<std::map<ValueType, std::make_unsigned_t<HashType>>, ValueType, HashType, MapZobristHash<ValueType, HashType>>; MapZobristHash() = default; template <typename Container> MapZobristHash(const Container& universal_set) { for (auto& val : universal_set) this->h[val] = (this->rng)(); } protected: static void ensure_key_existence(typename Base::container_type& h, const typename Base::value_type &v, typename Base::rng_type& rng) { if (auto it = h.find(v); it == h.end()) h[v] = rng(); } }; } // namespace suisen #endif // SUISEN_ZOBRIST_HASH
#line 1 "library/util/zobrist_hash.hpp" #include <algorithm> #include <array> #include <map> #include <vector> #include <random> namespace suisen { template <typename ContainerType, typename ValueType, typename HashType, typename Derived> struct ZobristHashBase { using container_type = ContainerType; using value_type = ValueType; using hash_type = std::make_unsigned_t<HashType>; using rng_type = std::mt19937_64; using self_type = Derived; template <typename ...Args> ZobristHashBase(Args &&...args) : rng(std::random_device{}()), h(std::forward<Args>(args)...) {} hash_type operator()(const value_type &val) { Self::ensure_key_existence(h, val, rng); return h[val]; } hash_type empty_set() const { return 0; } hash_type sigleton_set(const value_type& val) { return (*this)(val); } hash_type flip(hash_type old_hash, const value_type& val) { return old_hash ^ (*this)(val); } hash_type xor_set(hash_type set1, hash_type set2) const { return set1 ^ set2; } protected: rng_type rng; container_type h; private: struct Self : public self_type { using self_type::ensure_key_existence; }; }; template <typename HashType = std::uint64_t, std::enable_if_t<std::is_integral_v<HashType>, std::nullptr_t> = nullptr> struct VecZobristHash : public ZobristHashBase<std::vector<std::make_unsigned_t<HashType>>, std::size_t, HashType, VecZobristHash<HashType>> { using Base = ZobristHashBase<std::vector<std::make_unsigned_t<HashType>>, std::size_t, HashType, VecZobristHash<HashType>>; VecZobristHash() = default; VecZobristHash(typename Base::value_type max_val) : Base(max_val + 1) { std::generate(this->h.begin(), this->h.end(), this->rng); } protected: static void ensure_key_existence(typename Base::container_type& h, typename Base::value_type v, typename Base::rng_type& rng) { if (std::size_t old_size = h.size(); old_size <= v) { h.resize(v + 1); for (std::size_t i = old_size; i <= v; ++i) h[i] = rng(); } } }; template <std::size_t N, typename HashType = std::uint64_t, std::enable_if_t<std::is_integral_v<HashType>, std::nullptr_t> = nullptr> struct ArrZobristHash : public ZobristHashBase<std::array<std::make_unsigned_t<HashType>, N + 1>, std::size_t, HashType, ArrZobristHash<N, HashType>> { using Base = ZobristHashBase<std::array<std::make_unsigned_t<HashType>, N + 1>, std::size_t, HashType, ArrZobristHash<N, HashType>>; ArrZobristHash() { std::generate(this->h.begin(), this->h.end(), this->rng); } protected: static void ensure_key_existence(typename Base::container_type&, typename Base::value_type, typename Base::rng_type&) {} }; template <typename ValueType, typename HashType = std::uint64_t, std::enable_if_t<std::is_integral_v<HashType>, std::nullptr_t> = nullptr> struct MapZobristHash : public ZobristHashBase<std::map<ValueType, std::make_unsigned_t<HashType>>, ValueType, HashType, MapZobristHash<ValueType, HashType>> { using Base = ZobristHashBase<std::map<ValueType, std::make_unsigned_t<HashType>>, ValueType, HashType, MapZobristHash<ValueType, HashType>>; MapZobristHash() = default; template <typename Container> MapZobristHash(const Container& universal_set) { for (auto& val : universal_set) this->h[val] = (this->rng)(); } protected: static void ensure_key_existence(typename Base::container_type& h, const typename Base::value_type &v, typename Base::rng_type& rng) { if (auto it = h.find(v); it == h.end()) h[v] = rng(); } }; } // namespace suisen