#include #include #include #include #include #include namespace { template void print_matrix(const std::vector> &m) { for (const auto &row : m) { for (auto x : row) { std::cout << x << " "; } std::cout << "\n"; } std::cout << "\n"; } template class diagonal { std::vector> &matrix; std::size_t x; std::size_t y; class diagonal_iter { std::vector> &m; std::size_t x; std::size_t y; public: using difference_type = std::ptrdiff_t; using value_type = T; using pointer = T *; using reference = T &; using iterator_category = std::random_access_iterator_tag; diagonal_iter(std::vector> &matrix, std::size_t x, std::size_t y) : m(matrix), x(x), y(y) {} bool operator!=(const diagonal_iter &rhs) const { return m != rhs.m || x != rhs.x || y != rhs.y; } bool operator==(const diagonal_iter &rhs) const { return !(*this != rhs); } diagonal_iter &operator++() { x++; y++; return *this; } diagonal_iter operator--() { x--; y--; return *this; } reference operator*() const { return m[y][x]; } diagonal_iter operator-(difference_type n) const { return diagonal_iter{m, x - n, y - n}; } int operator-(const diagonal_iter &rhs) const { return x - rhs.x; } diagonal_iter operator+(difference_type n) const { return diagonal_iter{m, x + n, y + n}; } bool operator<(const diagonal_iter &rhs) const { return x < rhs.x; } diagonal_iter &operator=(const diagonal_iter &rhs) { if (this != &rhs) // not a self-assignment { this->m = rhs.m; this->x = rhs.x; this->y = rhs.y; } return *this; } }; public: diagonal(std::vector> &matrix, std::size_t x, std::size_t y) : matrix(matrix), x(x), y(y) {} diagonal_iter begin() const { return diagonal_iter{matrix, x, y}; } diagonal_iter end() const { auto max_x = matrix[y].size(); auto max_y = matrix.size(); auto steps = std::min(max_x - x, max_y - y); return diagonal_iter{matrix, x + steps, y + steps}; } }; template class diagonals { std::vector> &_matrix; class diagonals_iter { std::vector> &m; std::size_t x; std::size_t y; public: diagonals_iter(std::vector> &matrix, std::size_t x, std::size_t y) : m(matrix), x(x), y(y) {} bool operator!=(const diagonals_iter &rhs) const { return m != rhs.m || x != rhs.x || y != rhs.y; } diagonals_iter &operator++() { if (y != 0) { // iterating through diagonals down the first column y++; return *this; } // iterating the diagonals along the first row x++; if (x == m.front().size()) { // switching to diagonals in the first column x = 0; y++; } return *this; } diagonal operator*() const { return diagonal{m, x, y}; } }; public: diagonals(std::vector> &matrix) : _matrix(matrix) {} diagonals_iter begin() { return diagonals_iter{_matrix, 0, 0}; } diagonals_iter end() { return diagonals_iter{_matrix, 0, _matrix.size()}; } }; } // namespace class Solution { public: std::vector> diagonalSort(std::vector> mat) { for (auto d : diagonals(mat)) { std::sort(d.begin(), d.end()); } return mat; } }; static void test_case_1() { // Input: mat = [[3,3,1,1],[2,2,1,2],[1,1,1,2]] // Output: [[1,1,1,1],[1,2,2,2],[1,2,3,3]] Solution s; assert((s.diagonalSort(std::vector{std::vector{3, 3, 1, 1}, std::vector{2, 2, 1, 2}, std::vector{1, 1, 1, 2}}) == std::vector{std::vector{1, 1, 1, 1}, std::vector{1, 2, 2, 2}, std::vector{1, 2, 3, 3}})); } static void test_case_2() { // Input: mat = // [[11,25,66,1,69,7],[23,55,17,45,15,52],[75,31,36,44,58,8],[22,27,33,25,68,4],[84,28,14,11,5,50]] // Output: // [[5,17,4,1,52,7],[11,11,25,45,8,69],[14,23,25,44,58,15],[22,27,31,36,50,66],[84,28,75,33,55,68]] Solution s; assert((s.diagonalSort(std::vector{std::vector{11, 25, 66, 1, 69, 7}, std::vector{23, 55, 17, 45, 15, 52}, std::vector{75, 31, 36, 44, 58, 8}, std::vector{22, 27, 33, 25, 68, 4}, std::vector{84, 28, 14, 11, 5, 50}}) == std::vector{std::vector{5, 17, 4, 1, 52, 7}, std::vector{11, 11, 25, 45, 8, 69}, std::vector{14, 23, 25, 44, 58, 15}, std::vector{22, 27, 31, 36, 50, 66}, std::vector{84, 28, 75, 33, 55, 68}})); } int main() { test_case_1(); test_case_2(); return 0; }