#pragma once #include #include #include #include #include template concept SequentialCollection = requires(T c) { { c.size() } -> std::integral; { c.data() } -> std::same_as; }; template constexpr std::array operator+(const std::array & a, const std::array & b) { std::array r; auto out = r.begin(); out = std::copy(a.begin(), a.end(), out); std::copy(b.begin(), b.end(), out); return r; } template constexpr std::array, first * second> operator*(const std::array & a, const std::array & b) { std::array, first * second> r; auto out = r.begin(); for (const auto & ae : a) { for (const auto & be : b) { *out++ = {ae, be}; } } return r; } template constexpr auto operator*(const std::array & in, auto && f) { std::array out; for (auto outitr = out.begin(); const auto & v : in) { *outitr++ = f(v); } return out; } template constexpr auto & operator*=(std::span & in, auto && f) { for (auto & v : in) { f(v); } return in; } template typename C, typename... T> constexpr auto operator*(const C & in, auto && f) { C out; std::transform(in.begin(), in.end(), std::inserter(out, out.end()), f); return out; } template constexpr auto & operator+=(std::vector & in, std::vector && src) { in.reserve(in.size() + src.size()); std::move(src.begin(), src.end(), std::back_inserter(in)); return in; } template constexpr auto operator+(const std::vector & in, Vn && vn) { auto out(in); out.emplace_back(std::forward(vn)); return out; } template typename Direction = std::plus> static auto vectorOfN(std::integral auto N, unsigned int start = {}, unsigned int step = 1) { std::vector v; v.resize(N); std::generate_n(v.begin(), N, [&start, step, adj = Direction {}]() { return std::exchange(start, adj(start, step)); }); return v; }