fork download
  1. #include <utility>
  2. #include <vector>
  3. #include <algorithm>
  4. #include <iostream>
  5.  
  6. std::pair<int, int>
  7. rotated_local_next(int i, int j, int w, int h)
  8. {
  9. if(j == 0) //top , special case top-right
  10. {
  11. return i == w-1 ? std::make_pair(i, ++j) : std::make_pair(++i, j);
  12. }
  13. if(i == w-1) //right, special case bottom-right
  14. {
  15. return j == h-1 ? std::make_pair(--i, j) : std::make_pair(i, ++j);
  16. }
  17. if(j == h-1) //bottom, special case bottom-left
  18. {
  19. return i == 0 ? std::make_pair(i, --j) : std::make_pair(--i, j);
  20. }
  21. if(i == 0) //left, special case top-left
  22. {
  23. return j == 0 ? std::make_pair(++i, j): std::make_pair(i, --j);
  24. }
  25.  
  26. // cannot happen
  27. throw std::exception{};
  28. }
  29.  
  30. std::pair<int, int>
  31. rotated_matrix_next(int x, int y, int ring_i, int height, int width )
  32. {
  33. auto local_point = rotated_local_next(x-ring_i, y-ring_i, width-2*(ring_i), height-2*(ring_i));
  34. return std::make_pair(local_point.first + ring_i, local_point.second + ring_i);
  35. }
  36.  
  37. struct RingView
  38. {
  39. RingView(std::vector<std::vector<int>>& mat, int ringnumber)
  40. : matrix(mat)
  41. , rows(mat.size())
  42. , cols(mat[0].size())
  43. , ring(ringnumber)
  44. {}
  45.  
  46. std::vector<std::vector<int>>& matrix;
  47. int rows;
  48. int cols;
  49. int ring; // zero indexed
  50.  
  51. class ring_iterator : public std::iterator<std::forward_iterator_tag, int>
  52. {
  53. public:
  54.  
  55. ring_iterator(RingView* v = nullptr, int xpos = 0, int ypos = 0)
  56. : view(v)
  57. , x(xpos)
  58. , y(ypos)
  59. {}
  60.  
  61. ring_iterator(const ring_iterator& other) = default;
  62. ring_iterator(ring_iterator&& other) = default;
  63. ring_iterator& operator =(ring_iterator const&) = default;
  64. ring_iterator& operator=(ring_iterator&&) = default;
  65. virtual ~ring_iterator() = default;
  66.  
  67. RingView* view;
  68. int x;
  69. int y;
  70. int holder;
  71.  
  72. // Forward
  73. ring_iterator& operator++() {
  74. auto posnext = rotated_matrix_next(x, y, view->ring, view->cols, view->rows);
  75.  
  76. x = posnext.first;
  77. y = posnext.second;
  78. return *this;
  79. }
  80.  
  81. ring_iterator operator++(int) {
  82. auto posnext = rotated_matrix_next(x, y, view->ring, view->cols, view->rows);
  83. ring_iterator next_iter = *this;
  84. next_iter.x = posnext.first;
  85. next_iter.y = posnext.second;
  86. return next_iter;
  87. }
  88.  
  89. // equality required to test with end
  90. bool operator==(const ring_iterator& other) const {
  91. if(view == nullptr ){
  92. return other.view == nullptr;
  93. }
  94. return view->ring == other.view->ring && x == other.x && y == other.y;
  95. }
  96.  
  97. bool operator!=(const ring_iterator& other) const {
  98. return !(*this == other);
  99. }
  100.  
  101. // usually required
  102. int& operator*() {
  103. return view->matrix[x][y];
  104. }
  105. int* operator->() {
  106. return &(view->matrix[x][y]);
  107. }
  108. };
  109.  
  110. ring_iterator begin()
  111. {
  112. return ring_iterator(this, ring, ring);
  113. }
  114.  
  115. ring_iterator end()
  116. {
  117. return begin();
  118. }
  119.  
  120. int size() const
  121. {
  122. return 2*(rows+cols -2) - 4 * ring;
  123. }
  124. };
  125.  
  126. using Matrix = std::vector<std::vector<int>>;
  127.  
  128. void rotate_mat (Matrix &mat, int r){
  129. auto n_rings = std::min(mat.size(),mat[0].size())/2; // Number of rings
  130. for(auto ring_i=0; ring_i<n_rings; ++ring_i){
  131. RingView view(mat,ring_i);
  132. int r_modulo = (r % view.size() + view.size()) % view.size();
  133. auto next_location = view.begin();
  134. std::advance(next_location, r_modulo);
  135. std::rotate(view.begin(),next_location,view.end());
  136. }
  137. }
  138.  
  139. void print_matrix(Matrix &mat){
  140. for (auto& i : mat){
  141. for (auto& j : i) {
  142. std::cout << j << " ";
  143. }
  144. std::cout << "\n";
  145. }
  146. std::cout << "\n";
  147. };
  148.  
  149. int main() {
  150. std::vector<std::vector<int>> data = { {1,2,3,4}, {5,6,7,8}, {9,10,11,12}, {13,14,15,16}, {17, 18, 19, 20} };
  151. print_matrix(data);
  152. rotate_mat(data, -2);
  153. print_matrix(data);
  154. return 0;
  155. }
Success #stdin #stdout 0s 15248KB
stdin
Standard input is empty
stdout
1 2 3 4 
5 6 7 8 
9 10 11 12 
13 14 15 16 
17 18 19 20 

3 4 8 12 
2 14 10 16 
1 15 6 20 
5 11 7 19 
9 13 17 18