#pragma once #include typedef long long ll; typedef unsigned long long ull; template struct Coord { T x, y; Coord() : Coord(0, 0) {} Coord(const T x, const T y) { this->x = x; this->y = y; } Coord operator-() { return {-this->x, -this->y}; } Coord &operator+=(const Coord &other) { x += other.x; y += other.y; return *this; } Coord &operator-=(const Coord &other) { x -= other.x; y -= other.y; return *this; } Coord &operator*=(const T other) { x *= other; y *= other; return *this; } Coord &operator/=(const T other) { x /= other; y /= other; return *this; } std::vector> nearby(const Coord &cMin, const Coord &cMax) { std::vector> ret; const T xMin = std::max(this->x - 1, cMin.x); const T xMax = std::min(this->x + 1, cMax.x); const T yMin = std::max(this->y - 1, cMin.y); const T yMax = std::min(this->y + 1, cMax.y); for (T x = xMin; x <= xMax; x++) { for (T y = yMin; y <= yMax; y++) { Coord xy(x, y); if (*this != xy) { ret.push_back(xy); } } } return ret; } std::vector> nearby(const Coord &cMax) { return this->nearby(Coord(), cMax); } }; template Coord operator+(const Coord &lhs, const Coord &rhs) { Coord result = lhs; result += rhs; return result; } template Coord operator-(const Coord &lhs, const Coord &rhs) { Coord result = lhs; result -= rhs; return result; } template Coord operator*(const Coord &lhs, const T rhs) { Coord result = lhs; result *= rhs; return result; } template Coord operator/(const Coord &lhs, const T rhs) { Coord result = lhs; result /= rhs; return result; } template inline bool operator==(const Coord &lhs, const Coord &rhs) { return lhs.x == rhs.x && lhs.y == rhs.y; } template <> struct std::hash> { std::size_t operator()(const Coord &c) const noexcept { return (c.x << (sizeof(std::size_t) / 2)) - c.x + c.y; } }; template <> struct std::hash> { std::size_t operator()(const Coord &c) const noexcept { return (c.x << (sizeof(std::size_t) / 2)) - c.x + c.y; } };