Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to rotate a matrix in an array in javascript

(disclosure, I'm mostly math illiterate).

I have an array in this format:

var grid = [
  [0,0], [0,1], [0,2], [0,3],
  [1,0], [1,1], [1,2], [1,3],
  [2,0], [2,1], [2,2], [2,3],
  [3,0], [3,1], [3,2], [3,3]
];

I need to "rotate" it by 90deg increments, so it's like this:

var grid = [
  [3,0], [2,0], [1,0], [0,0], 
  [3,1], [2,1], [1,1], [0,1], 
  [3,2], [2,2], [1,2], [0,2], 
  [3,3], [2,3], [1,3], [0,3] 
];

How do I accomplish this in Javascript?

like image 959
methodofaction Avatar asked Mar 02 '13 05:03

methodofaction


People also ask

How do you rotate a matrix by 45?

The formula of this rotation is : RM[x + y - 1][n - x + y] = M[x][y], where RM means rotated matrix, M the initial matrix, and n the dimension of the initial matrix (which is n x n). So, a32, from the third row and second column will get to the fourth row and the fourth column. Any help is much appreciated.


4 Answers

Rotating a two dimensional m x n matrix

Those looking for Rotating a two dimensional matrix (a more general case) here is how to do it.

example: Original Matrix:

[
  [1,2,3],
  [4,5,6], 
  [7,8,9]
]

Rotated at 90 degrees:

[
    [7,4,1]
    [8,5,2]
    [9,6,3]
]

This is done in following way:

matrix[0].map((val, index) => matrix.map(row => row[index]).reverse())
like image 91
Nitin Jadhav Avatar answered Oct 18 '22 20:10

Nitin Jadhav


Credit goes to this answer for the actual rotation method.

My method was pretty straightforward. Just determine what the row length was, and then iterate through each item, converting the array index to x/y equivalents and then apply the method used in the linked answer to rotate. Finally I converted the rotated X/Y coordinates back to an array index.

var grid = [
  [0,0], [0,1], [0,2], [0,3],
  [1,0], [1,1], [1,2], [1,3],
  [2,0], [2,1], [2,2], [2,3],
  [3,0], [3,1], [3,2], [3,3]
]; 

var newGrid = [];
var rowLength = Math.sqrt(grid.length);
newGrid.length = grid.length

for (var i = 0; i < grid.length; i++)
{
    //convert to x/y
    var x = i % rowLength;
    var y = Math.floor(i / rowLength);

    //find new x/y
    var newX = rowLength - y - 1;
    var newY = x;

    //convert back to index
    var newPosition = newY * rowLength + newX;
    newGrid[newPosition] = grid[i];
}

for (var i = 0; i < newGrid.length; i++)
{   
    console.log(newGrid[i])
}

The output:

[3, 0] [2, 0] [1, 0] [0, 0]  
[3, 1] [2, 1] [1, 1] [0, 1]  
[3, 2] [2, 2] [1, 2] [0, 2]  
[3, 3] [2, 3] [1, 3] [0, 3]  

Fiddle for the lazy. And a 5x5 grid fiddle to demonstrate that the algorithm works for N grid sizes as long as they are square.

like image 42
lmortenson Avatar answered Oct 18 '22 20:10

lmortenson


These are two function for clockwise and counterclockwise 90-degree rotation:

    function rotateCounterClockwise(a){
        var n=a.length;
        for (var i=0; i<n/2; i++) {
            for (var j=i; j<n-i-1; j++) {
                var tmp=a[i][j];
                a[i][j]=a[j][n-i-1];
                a[j][n-i-1]=a[n-i-1][n-j-1];
                a[n-i-1][n-j-1]=a[n-j-1][i];
                a[n-j-1][i]=tmp;
            }
        }
        return a;
    }

    function rotateClockwise(a) {
        var n=a.length;
        for (var i=0; i<n/2; i++) {
            for (var j=i; j<n-i-1; j++) {
                var tmp=a[i][j];
                a[i][j]=a[n-j-1][i];
                a[n-j-1][i]=a[n-i-1][n-j-1];
                a[n-i-1][n-j-1]=a[j][n-i-1];
                a[j][n-i-1]=tmp;
            }
        }
        return a;
    }
like image 23
Aryan Firouzian Avatar answered Oct 18 '22 21:10

Aryan Firouzian


I don't really need to deal with indices, since I can copy the values from one place to the other, this simplifies the answer a bit:

var grid = [
  [0,0], [0,1], [0,2], [0,3], [0,4],
  [1,0], [1,1], [1,2], [1,3], [1,4],
  [2,0], [2,1], [2,2], [2,3], [2,4],
  [3,0], [3,1], [3,2], [3,3], [3,4],
  [4,0], [4,1], [4,2], [4,3], [4,4]
]; 

var side = Math.sqrt(grid.length);

var rotate = function(d,i){
   return [Math.abs(i % side - side+1), Math.floor(i/side)]
}
grid = grid.map(rotate);

You can see a jsfiddle here: http://jsfiddle.net/KmtPg/

like image 28
methodofaction Avatar answered Oct 18 '22 20:10

methodofaction