#include #include #include class Solution { struct indices { int x; int y; bool operator==(const indices &other) const = default; indices &operator+=(const indices &other) { x += other.x; y += other.y; return *this; } friend indices operator+(indices left, const indices &right) { return left += right; } int &operator[](std::vector> &mat) const { return mat[y][x]; } }; struct spiral_indices { spiral_indices(const std::vector> &matrix) : x_bounds{-1, static_cast(matrix.size() ? matrix[0].size() : 0)}, y_bounds{-1, static_cast(matrix.size())} {} bool done() const { return !in_bounds(idx); } spiral_indices &operator++() { // update bounds and change the direction if cannot move if (!in_bounds(idx + d)) { // change the direction d = {-d.y, d.x}; // get the magnitude of the vector auto flat_d = d.x + d.y; // decide whether we're moving x or y bounds auto &bounds = d.x ? x_bounds : y_bounds; if (flat_d > 0) { bounds.x++; } else { bounds.y--; } } idx += d; return *this; } int &operator[](std::vector> &mat) const { return idx[mat]; } private: indices idx{0, 0}; indices d{1, 0}; indices x_bounds, y_bounds; bool in_bounds(const indices &idx) const { return (x_bounds.x < idx.x && idx.x < x_bounds.y) && (y_bounds.x < idx.y && idx.y < y_bounds.y); } }; public: std::vector> generateMatrix(int n) { auto length = static_cast(n); std::vector> spiral{length, std::vector(length, 0)}; int i = 1; for (spiral_indices idx{spiral}; !idx.done(); ++idx) { idx[spiral] = i++; } return spiral; } }; int main() { Solution s; assert((s.generateMatrix(0) == std::vector>{})); assert((s.generateMatrix(1) == std::vector>{{1}})); assert( (s.generateMatrix(2) == std::vector>{{1, 2}, {4, 3}})); for (auto &&row : s.generateMatrix(3)) { for (auto x : row) std::cout << x << " "; std::cout << "\n"; } assert((s.generateMatrix(3) == std::vector>{{1, 2, 3}, {8, 9, 4}, {7, 6, 5}})); return 0; }