#include <cassert> #include <iostream> #include <vector> 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<std::vector<int>> &mat) const { return mat[y][x]; } }; struct spiral_indices { spiral_indices(const std::vector<std::vector<int>> &matrix) : x_bounds{-1, static_cast<int>(matrix.size() ? matrix[0].size() : 0)}, y_bounds{-1, static_cast<int>(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<std::vector<int>> &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<std::vector<int>> generateMatrix(int n) { auto length = static_cast<std::size_t>(n); std::vector<std::vector<int>> spiral{length, std::vector<int>(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<std::vector<int>>{})); assert((s.generateMatrix(1) == std::vector<std::vector<int>>{{1}})); assert( (s.generateMatrix(2) == std::vector<std::vector<int>>{{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<std::vector<int>>{{1, 2, 3}, {8, 9, 4}, {7, 6, 5}})); return 0; }