#include #include #include using matrix = std::vector>; template class diagonal { using matrix_t = std::vector>; matrix_t& matrix; std::size_t x; std::size_t y; class diagonal_iter { // we need to keep reference to the matrix itself std::reference_wrapper m; // we need to be able to tell our current position 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(matrix_t& matrix, std::size_t x, std::size_t y) : m(matrix) , x(x) , y(y) { } bool operator==(const diagonal_iter& rhs) const { return x == rhs.x && y == rhs.y && m.get() == rhs.m.get(); } diagonal_iter& operator++() { // we are moving along the diagonal, so we increment both ‹x› and ‹y› // at the same time x++; y++; return *this; } reference operator*() const { return m.get()[y][x]; } // exactly opposite to the incrementation diagonal_iter operator--() { x--; y--; return *this; } // moving ‹n› steps back is same as calling decrementation ‹n›-times, so // we can just return a new iterator and subtract ‹n› from both // coordinates in the matrix diagonal_iter operator-(difference_type n) const { return diagonal_iter { m, x - n, y - n }; } // here we assume that we are given two iterators on the same diagonal difference_type operator-(const diagonal_iter& rhs) const { assert(m.get() == rhs.m.get()); return x - rhs.x; } // counterpart of moving ‹n› steps backwards diagonal_iter operator+(difference_type n) const { return diagonal_iter { m, x + n, y + n }; } // we compare the coordinates, and also assume that those 2 iterators are // lying on the same diagonal bool operator<(const diagonal_iter& rhs) const { assert(m.get() == rhs.m.get()); return x < rhs.x && y < rhs.y; } }; public: diagonal(matrix_t& 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(); // we need to find the distance in which we get out of bounds (either in // column or row) auto steps = std::min(max_x - x, max_y - y); return diagonal_iter { matrix, x + steps, y + steps }; } }; template class diagonals { using matrix_t = std::vector>; class diagonals_iter { matrix_t& m; std::size_t x; std::size_t y; public: diagonals_iter(matrix_t& matrix, std::size_t x, std::size_t y) : m(matrix) , x(x) , y(y) { } bool operator!=(const diagonals_iter& rhs) const { // iterators are not equal if they reference different matrices, or // their positions differ return x != rhs.x || y != rhs.y || m != rhs.m; } 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 }; } }; matrix_t& _matrix; public: diagonals(matrix_t& m) : _matrix(m) { } diagonals_iter begin() { return diagonals_iter { _matrix, 0, 0 }; } diagonals_iter end() { return diagonals_iter { _matrix, 0, _matrix.size() }; } }; class Solution { public: matrix diagonalSort(matrix mat) { // we iterate over the diagonals for (auto d : diagonals(mat)) { // and we sort each diagonal std::sort(d.begin(), d.end()); } // we take the matrix by copy, so we can sort in-situ and return the copy // that we sorted 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; }