Ruby Arrays - Find the sum of the diagonals

I have not seen this before, but I was wondering how you can find the sums of both diagonals of a 2D array in Ruby. Let's say you have a simple array with 3 rows and 3 columns.

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

I can break it into groups of three using

array.each_slice(3).to_a

Now will be

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

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

In this case, the diagonals are

1 + 5 + 9 = 15
3 + 5 + 7 = 15

Thus, the total amount will be 15 + 15 = 30

I thought I could do something like

diagonal_sum = 0
for i in 0..2
  for j in 0..2
    diagonal_sum += array[i][j]
  end
end
+5
source share
7 answers

Here is my attempt:

array = [1,2,3,4,5,6,7,8,9]
sliced = array.each_slice(3).to_a
# As sliced size is 3, I took 2, i.e. 3 - 1
(0..2).map { |i| sliced[i][i] } #=> [1, 5, 9]
(0..2).map { |i| sliced[i][-i-1] } # => [3, 5, 7]
(0..2).map { |i| sliced[i][i] }.reduce :+
# => 15
(0..2).map { |i| sliced[i][-i-1] }.reduce :+
# => 15

In accordance with the observation above, it seems that in one iteration you can solve:

left_diagonal, right_diagoal = (0..2).each_with_object([[], []]) do |i, a|
  a[0] << sliced[i][i]
  a[1] << sliced[i][-i-1]
end

left_diagonal.reduce(:+) # => 15
right_diagonal.reduce(:+) # => 15

OOP code style added:

class SquareMatrix
  attr_reader :array, :order

  def initialize array, n
    @array = array.each_slice(n).to_a
    @order = n
  end

  def collect_both_diagonal_elements
    (0...order).collect_concat { |i| [ array[i][i], array[i][-i-1] ] }
  end

  def collect_left_diagonal_elements
    (0...order).collect { |i| array[i][i] }
  end 

  def collect_right_diagonal_elements
    (0...order).collect { |i| array[i][-i-1] }
  end

  def sum_of_diagonal_elements type
    case type
    when :all   then collect_both_diagonal_elements.reduce(0, :+)
    when :right then collect_right_diagonal_elements.reduce(0, :+)
    when :left  then collect_left_diagonal_elements.reduce(0, :+)
    end
  end
end

array = [1,2,3,4,5,6,7,8,9]
sqm   = SquareMatrix.new array, 3
sqm.collect_both_diagonal_elements # => [1, 3, 5, 5, 9, 7]
sqm.sum_of_diagonal_elements :all # => 30
sqm.collect_left_diagonal_elements # => [1, 5, 9]
sqm.sum_of_diagonal_elements :left # => 15
sqm.collect_right_diagonal_elements # => [3, 5, 7]
sqm.sum_of_diagonal_elements :right # => 15
+8
source

Mainly for academic discussion:

"", "". , ( , ):

require 'Matrix'
a = array.each_slice(3).to_a
Matrix[*a].trace 

, - "" , , , ( each_slice - , reverse . ):

Matrix[*a.reverse].trace
+5

# map.with_index... @xlembouras, heres

first_diagonal = array.map.with_index {|row, i| row[i]} .inject :+
inverted_diagonal = array.map.with_index {|row, i| row[-i-1]} .inject :+

:

first_diagonal, inverted_diagonal = (array.map.with_index {|row, i| row[i]} .inject :+) , (array.map.with_index {|row, i| row[-i-1]} .inject :+)

:

, , #map_with_index:

:

i = -1
array.map { |row| row[i=i+1] }.inject :+

( ):

i = array.length
array.map { |row| row[i=i-1] }.inject :+
+2
a = [1,2,3,4,5,6,7,8,9]
p a.values_at(0,2,4,4,6,8).inject(&:+) #=> 30
+1

()

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

dimension = array.length

array.flatten.map.with_index do |x,i|
  x if [0, dimension - 1].include?(i % dimension)
end.compact.inject(:+)

#=> 30
0

slice:

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

We visualize arrhow:

1 2 3
4 5 6
7 8 9

n = Math.sqrt(arr.size).round 
  #=> 3

For the main diagonal:

(0...arr.size).step(n+1).reduce(0) { |t,i| t+arr[i] }
  #=> 15 

For off-diagonal:

(n-1..arr.size-n).step(n-1).reduce(0) { |t,i| t+arr[i] }
  #=> 15  

Another example:

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

1 2 3 4
5 6 7 8
9 0 1 2
3 4 5 6

n = Math.sqrt(arr.size).round 
  #=> 4

(0...arr.size).step(n+1).reduce(0) { |t,i| t+arr[i] } +
(n-1..arr.size-n).step(n-1).reduce(0) { |t,i| t+arr[i] }
  #=> 14 + 14 => 28
0
source
require 'Matrix'

arr = [[1, 3, 4], [2, 5, 7], [6, 7, 8]]

diag1 = Matrix[*arr].tr
diag2 = Matrix[*arr.reverse].tr
0
source

All Articles