13

I want to rotate a matrix 90 degrees clockwise. This amounts to making the first column in the input the first row of the output, the second column of the input the 2nd row of the output, and the 3rd column of the input the 3rd row of the output. Note that the bottom of the column=the beginning of the row, because of the 90 degree rotation.

For example:

$matrix=    [[1, 2, 3]
             [4, 5, 6], 
             [7, 8, 9]];

rotate90degrees($matrix)=      [[7, 4, 1],
                                [8, 5, 2],
                                [9, 6, 3]]

What I know is I have first transpose the matrix and then swap the columns to rotate the matrix by 90 degrees. How can this be applied to php?

chiliNUT
  • 18,989
  • 14
  • 66
  • 106
Ahmed Safadi
  • 4,402
  • 37
  • 33

7 Answers7

12

I showed you how to transpose an array in answer to a previous question, to rotate 90 degrees, use that transpose logic, and then reverse the order of the values in each row in turn:

$matrix = [
    [1, 2, 3],
    [4, 5, 6], 
    [7, 8, 9],
];

array_unshift($matrix, null);
$matrix = call_user_func_array('array_map', $matrix);
$matrix = array_map('array_reverse', $matrix);
var_dump($matrix);

Demo

Community
  • 1
  • 1
Mark Baker
  • 209,507
  • 32
  • 346
  • 385
  • @Gannet - [An answer that I provided to a similar question here provides an explanation](http://stackoverflow.com/questions/30082814/create-transpose-matrix-using-php/30082922#30082922) – Mark Baker Sep 08 '16 at 20:35
  • you can replace ```array_unshift($matrix, null); $matrix = call_user_func_array('array_map', $matrix);``` with simple ```$matrix = array_map(null, ...$matrix);``` – lulco Oct 07 '19 at 12:49
5

Another reliable option:

function rotateMatrix90( $matrix )
{
    $matrix = array_values( $matrix );
    $matrix90 = array();

    // make each new row = reversed old column
    foreach( array_keys( $matrix[0] ) as $column ){
        $matrix90[] = array_reverse( array_column( $matrix, $column ) );
    }

    return $matrix90;
}

Less clever than @mark-baker's by far. Maybe more clear.

daggerhart
  • 441
  • 4
  • 8
3

php doesn't have concepts like "transpose" for a matrix without adding some sort of linear algebra library. you can do it natively by eaching through the matrix and swapping some indexes

<?php

function rotate90($mat) {
    $height = count($mat);
    $width = count($mat[0]);
    $mat90 = array();

    for ($i = 0; $i < $width; $i++) {
        for ($j = 0; $j < $height; $j++) {
            $mat90[$height - $i - 1][$j] = $mat[$height - $j - 1][$i];
        }
    }

    return $mat90;
}

$mat = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
print_r($mat);
//123
//456
//789
print_r(rotate90($mat));
//741
//852
//963


$mat = [[1, 2, 3], [4, 5, 6], [7, 8, 9], ["a", "b", "c"]];
print_r($mat);
//123
//456
//789
//abc
print_r(rotate90($mat));
//a741
//b852
//c963
chiliNUT
  • 18,989
  • 14
  • 66
  • 106
  • 1
    If you want to rotate the matrix more than once, you'll need to fix the keys for the outer array. Add `$mat90 = array_values($mat90);` before `return $mat90;` – daggerhart Mar 14 '17 at 13:18
2

You can concisely transpose the matrix data in a one-liner. The ... spread operator unpacks the input array's subarrays into sets of columnar data. Call array_reverse() on the columns of data sent to the custom callback function's scope.

Code: (Demo)

var_export(array_map(fn() => array_reverse(func_get_args()), ...$matrix));

Or:

var_export(array_map(fn(...$col) => array_reverse($col), ...$matrix));

Output (from either):

[[7,4,1],
 [8,5,2],
 [9,6,3]]
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
0

The below code is using additional space.

<?php

function rotate90degrees()
{
    $matrix = [[1,2,3],
               [4,5,6],
               [7,8,9]];
               
    $k = 0;
    $len = count($matrix[0]);
    $tmp = [];
    
    // Create a new matrix with [[0,0,0],[0,0,0],[0,0,0]]
    while($k < $len) {
        $row = [];
        $l = 0;
        while($l < $len) {
            $row[] = 0;
            $l++;
        }
        $tmp[] = $row;
        $k++;
    }
    
    // Rotate through the given matrix and fill out the above created new matrix
    for($i=0; $i<$len; $i++) {
        for($j=$len-1; $j>=0; $j--) {
            $tmp[$i][$j] = $matrix[$j][$i];
        }
        $tmp[$i] = array_reverse($tmp[$i]);
    }
    
    return $matrix;
}

Below function does not use additional space.

<?php

function rotate90degreesWithoutAdditionalSpace()
{
    $matrix = [[1,2,3],
               [4,5,6],
               [7,8,9]];
               
    $len = count($matrix);
    
    // Swap the rows columns.
    for($i=0; $i<$len; $i++) {
        for($j=$i; $j<$len; $j++) {
            $tmp = $matrix[$i][$j];
            $matrix[$i][$j] = $matrix[$j][$i];
            $matrix[$j][$i] = $tmp;
        }
    }
    
    // Swap the elements from both ends of each row until the centered element in the row.
    for($i=0; $i<$len; $i++) {
        for($j=0; $j<floor($len/2); $j++) {
            $tmp = $matrix[$i][$j];
            $matrix[$i][$j] = $matrix[$i][$len-1-$j];
            $matrix[$i][$len-1-$j] = $tmp;
        }
    }
    
    return $matrix;
}
    
Sukeshini
  • 1,241
  • 2
  • 23
  • 48
0

you can rotate matrix cw using this code:

function rotateCW($arr){
    return array_map(function($row, $i) use ($arr){
        return array_reverse(array_column($arr, $i));
    }, $arr[0], array_keys($arr[0]));
}

and rotate it CCW using this code:

function rotateCCW($arr){
    return array_map(function($row, $i) use ($arr){
        return array_column($arr, count($arr[0]) - 1 -$i);
    }, $arr[0], array_keys($arr[0]));
}
0
function rotate90($a) {
  $cnt = count($a);
  $b = $a;
  
  for ($i = 0; $i < $cnt; $i++) {
    for ($j = 0; $j < $cnt; $j++) {
      $b[$j][$cnt-1-$i] = $a[$i][$j];
    }
  }

  return $b;
}
mikoop
  • 1,981
  • 1
  • 18
  • 18
ram
  • 1
  • 2