#pragma once #include #include #include "utils.hpp" namespace aoc2019 { template class Point : public std::array { public: constexpr Point& operator +=(Point other) { for (std::size_t i = 0; i < L; ++i) { (*this)[i] += other[i]; } return *this; } constexpr Point operator+(Point other) const { auto result = *this; result += other; return result; } constexpr Point& operator -=(Point other) { for (std::size_t i = 0; i < L; ++i) { (*this)[i] -= other[i]; } return *this; } constexpr Point operator-(Point other) const { auto result = *this; result -= other; return result; } constexpr T l1() const { T result = 0; for (auto e : *this) { result += std::abs(e); } return result; } }; template std::pair, Point> bounding_box(const std::unordered_map, Ignored> &data) { Point lower, upper; std::fill(lower.begin(), lower.end(), std::numeric_limits::max()); std::fill(upper.begin(), upper.end(), std::numeric_limits::min()); for (auto &entry : data) { for (int i = 0; i < N; ++i) { lower[i] = std::min(entry.first[i], lower[i]); upper[i] = std::max(entry.first[i], upper[i]); } } return {lower, upper}; } } namespace std { // Make point usable with unordered collections. template struct hash> { size_t operator()(const aoc2019::Point &o) const { size_t seed = 0; for (auto i : o) { aoc2019::combine_hash(seed, i); } return seed; } }; }