/*
Rotate by +90:
--------------
     - Transpose
     - Reverse each row
     
Rotate by -90:
-------------
     - Transpose
     - Reverse each column

Rotate by +180:
---------------

Method 1: Rotate by +90 twice

Method 2: Reverse each row and then reverse each column

Rotate by -180:
---------------
Method 1: Rotate by -90 twice

Method 2: Reverse each column and then reverse each row

Method 3: Reverse by +180 as they are same


Complixity: O(n^2) time and O(1) space algorithm
*/


#include <iostream>

/*
int** getRotate90PlusMatrix(int array[][4], int size) 
{
   int** rotated = new int*[size];

   for (int i = 0; i < size; i++)
      for (int j = 0; j < size; j++)
         rotated[i][j]  =  array[j][size-1-i];

   return rotated;
}
*/



void Rotate90Plus(int array[][4], int size) 
{
   int n = size, temp;

   for (int i = 0; i < n/2; i++) {
      for (int j = 1; j < n-i; j++) { 

         temp                 =  array[i][j];
         array[i][j]          =  array[j][n-1-i];
         array[j][n-1-i]      =  array[n-1-i][n-1-j];
         array[n-1-i][n-1-j]  =  array[n-1-j][i];
         array[n-1-j][i]      =  temp;
      }
   }

}



void Rotate90Minus(int array[][4], int size) 
{
   int n = size, temp;

   for (int i = 0; i < n/2; i++) {
      for (int j = 1; j < n-i; j++) { 

         temp                 =  array[i][j];
         array[i][j]          =  array[n-1-j][i];
         array[n-1-j][i]      =  array[n-1-i][n-1-j];
         array[n-1-i][n-1-j]  =  array[j][n-1-i];
         array[j][n-1-i]      =  temp;
      }
   }

}



void Rotate180(int array[][4], int size) 
{
   int n = size;

   for (int i = 0; i < n/2; i++) 
      for (int j = 0; j < n; j++) 
         std::swap( array[i][j], array[n-1-i][n-1-j] );
}






void PrintMatrix(int array[][4], int size) 
{
   for (int i=0; i < size; i++) {

      if(i%4) std::cout << "\n";
      for (int j=0; j < size; j++)
         std::cout << array[i][j] << "  ";
   }

   std::cout << "\n";
}



int main()
{
   int a[4][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 0, 1, 2}, {3, 4, 5, 6} };

   std::cout << "Original matrix: " << std::endl;
   PrintMatrix(a, 4);


   Rotate90Plus(a, 4);
   std::cout << "\nRotated original matrix +90 degree: " << std::endl;
   PrintMatrix(a, 4);



   Rotate90Minus(a, 4);
   std::cout << "\nRotated previous matrix -90 degree: " << std::endl;
   PrintMatrix(a, 4);



   Rotate180(a, 4);
   std::cout << "\nRotated original matrix 180 degree: " << std::endl;
   PrintMatrix(a, 4);

   return 0;
}
