diff --git a/problems/sort-the-matrix-diagonally.cpp b/problems/sort-the-matrix-diagonally.cpp new file mode 100644 index 0000000..9ad363d --- /dev/null +++ b/problems/sort-the-matrix-diagonally.cpp @@ -0,0 +1,230 @@ +#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; +}