Alan
Alan

Reputation: 2639

Getting two diagonals of a Matrix

I'm using this Matrix class: http://ruby-doc.org/stdlib-2.0.0/libdoc/matrix/rdoc/Matrix.html

I'm instantiating it this way:

@matrix = Matrix.build(3,3) { |row, col| Cell.new }

How can I get the elements from both diagonals? I found I can get the elements from the upper left to the lower right diagonal this way:

@matrix.each(:diagonal).to_a

But I cant find a way to get the elements in the upper right to lower left diagonal.

Upvotes: 1

Views: 825

Answers (2)

Cary Swoveland
Cary Swoveland

Reputation: 110745

Suppose:

require 'matrix'

m = Matrix[[1,2,3],
           [4,5,6],
           [7,8,9]]
  #=> Matrix[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

Obtaining the main diagonal is easy. Let's make it a Matrix method.

class Matrix
  def extract_diagonal
    each(:diagonal).to_a
  end
end

m.extract_diagonal
  # => [1, 5, 9]

One way of obtaining the antidiagonal1 is to rotate the matrix "90 degrees" and then take the main diagonal of that matrix. To perform the rotation, here's another Matrix method I've found useful in various situations:

class Matrix
  def rotate
    Matrix[*to_a.map(&:reverse).transpose]
  end
end

For example:

m.rotate
  #=> Matrix[[3, 6, 9],
  #          [2, 5, 8],
  #          [1, 4, 7]] 

The antidiagonal of m is therefore:

m.rotate.extract_diagonal
  #=> [3, 5, 7] 

1. According to Wiki, the diagonal that goes from the top left to the bottom right of a square matrix is the "main diagonal (sometimes principal diagonal, primary diagonal, leading diagonal, or major diagonal)", whereas the diagonal that goes from the top right to bottom left is the "antidiagonal (sometimes counterdiagonal, secondary diagonal, trailing diagonal or minor diagonal)".

Upvotes: 3

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121010

Diagonal:

@matrix.square? && ([email protected]_size).map { |i| @matrix[i, i] }

Upper-right⇒lower-left diagonal:

@matrix.square? && ([email protected]_size).map do |i|
  @matrix[i, @matrix.row_size - 1 - i]
end

Check for @matrix.square? ensures that the diagonal exists, after all.

Upvotes: 3

Related Questions