2
\$\begingroup\$

The idea is picked up from here and the following is my PHP implementation of it. As it mentions, 90 degree matrix rotation basically shifts columns into rows. For example:

|1,2,3|     becomes      |7,4,1|
|4,5,6|   ----------->>  |8,5,2|
|7,8,9|                  |9,6,3|

Notice how row 1,2,3, after rotation has become column.The solution is built on this pattern.

Here's the code:

class MatrixRotator
{
    public static function rotate($matrix)
    {
        $result_arr=[];
        for($i=0; $i<count($matrix); $i++)
        {
            $inner_arr = [];
            for($j=0; $j<count($matrix[$i]); $j++)
            {
                $item = $matrix[$j][$i];
                array_unshift($inner_arr, $item);
            }
            array_push($result_arr, $inner_arr);
        }
        return $result_arr;
    }
}


print_r(MatrixRotator::rotate([[1,2,3],[4,5,6],[7,8,9]]));

Here's the output:

|7,4,1|
|8,5,2|
|9,6,3|
\$\endgroup\$
  • 1
    \$\begingroup\$ Did you write the code yourself? Only code that you have written yourself is on-topic on this site. Please edit your question to remove any doubts that this code was written by you; unless, of course, you didn't write it. \$\endgroup\$ – Zeta Mar 31 '18 at 10:08
  • \$\begingroup\$ As you clarified with your edit, I retracted my down and close vote. \$\endgroup\$ – πάντα ῥεῖ Mar 31 '18 at 10:58
2
\$\begingroup\$

There's nothing really wrong with your class, but you could use array functions and foreach instead of for.

Also, calling your class MatrixRotator is a bit weird. A class is used to combine and isolate several methods (= functions) and properties (= variables) into a handy package. A rotate() method would probably be part of a set of methods which can modify the matrix. And when that is the case it would make sense to store the matrix data in the matrix class. This would then require a set and get method.

This would result in something like this:

class Matrix
{
  private $data = [];

  public function __construct($data)
  // accepts an array with matrix data and stores it
  {
    $this->data = $data;
  }

  public function rotateClockwise()
  // rotate a matrix once clockwise
  {
    // check that the matrix contains data
    if (isset($this->data[0]) && is_array($this->data[0]))
    {
      // perform the actual rotation
      $rotated = [];
      foreach (array_keys($this->data[0]) as $columnKey)
      {
        $rotated[] = array_reverse(array_column($this->data,$columnKey));
      }
      $this->data = $rotated;
    }
    // return this class so this method can be chained
    return $this;
  }

  public function getData()
  // returns the stored matrix
  {
    return $this->data;
  }
}

It can then be used like this:

// creation of a matrix
$matrix = new Matrix([[1,2,3],[4,5,6],[7,8,9]]);

// rotation and output
echo '<pre>';
print_r($matrix->rotateClockwise()->getData());
echo '</pre>';

It is now easy to put other matrix manipulation methods into this class. For instance, by leaving out the array_reverse() from rotateClockwise() you will get a rotateAntiClockwise() method. So let's do that:

class Matrix
{
  private $data = [];

  public function __construct($data)
  {
    $this->data = $data;
    if (!$this->isValid()) trigger_error("Matrix data is invalid.");
  }

  public function isValid()
  {
    if (!is_array($this->data)) return FALSE;
    foreach ($this->data as $row)
    {
      if (!is_array($row)) return FALSE;
    }
    return TRUE;
  }

  public function reverseEachRow()
  {
    if ($this->isValid())
    {
      foreach ($this->data as $rowKey => $row)
      {
        $this->data[$rowKey] = array_reverse($row);
      }
    }
    return $this;
  }

  public function rotateAntiClockwise()
  {
    if ($this->isValid() && isset($this->data[0]))
    {
      $rotated = [];
      foreach (array_keys($this->data[0]) as $columnKey)
      {
        $rotated[] = array_column($this->data,$columnKey);
      }
      $this->data = $rotated;
    }
    return $this;
  }

  public function rotateClockwise()
  {
    return $this->rotateAntiClockwise()
                ->reverseEachRow();
  }

  public function getData()
  {
    return $this->isValid() ? $this->data : FALSE;
  }

}

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

echo '<pre>';
print_r($matrix->rotateClockwise()->getData());
echo '</pre>';

I left out all comments, to keep the code short, and I also centralized the validity check. This goes beyond your question, but shows you why you wouldn't want to call your class MatrixRotator, it is too specific.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.