Ruby Arrays - 查找对角线的总和

时间:2015-03-07 16:29:37

标签: ruby arrays

以前没见过这个,但我想知道如何在Ruby中找到2D数组的两个对角线的总和。假设你有一个简单的数组,有3行3列。

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

我可以使用

将其分成三个一组
array.each_slice(3).to_a

现在是

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

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

在这种情况下,对角线是

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

所以总和将是15 + 15 = 30

我以为我可以做点什么

diagonal_sum = 0
for i in 0..2
  for j in 0..2
    diagonal_sum += array[i][j]
  end
end

8 个答案:

答案 0 :(得分:8)

这是我的尝试:

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

按照上面的观察,你可以在一次迭代中解决:

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 代码样式:

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

答案 1 :(得分:5)

以下主要用于学术讨论:

对于主对角线,您正在寻找为“Matrix”类定义的“跟踪”功能。所以下面的方法会起作用(虽然它没有让你对方的另一个对角线,我不会打赌它的效率):

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

要获得另一个对角线,你必须以某种方式“翻转”矩阵,所以以下似乎可行(因为each_slice的结果是一个行数组,reverse反转了它的顺序反转列的顺序更加困难):

Matrix[*a.reverse].trace

答案 2 :(得分:2)

我完全忘记了#map.with_index ...感谢@xlembouras,这是一个单行

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 :+

答案 3 :(得分:1)

a = [1,2,3,4,5,6,7,8,9]
p a.values_at(0,2,4,4,6,8).inject(&:+) #=> 30

答案 4 :(得分:0)

我会尝试迭代数组并根据(分组)数组的长度保留我需要的值

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

答案 5 :(得分:0)

您不需要先申请slice

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

我们将arr视为:

1 2 3
4 5 6
7 8 9

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

对于主对角线:

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

对于非对角线:

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

另一个例子:

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

答案 6 :(得分:0)

exec

答案 7 :(得分:-1)

def diagonal(array)
 single=array.flatten
 new=[]
 i=array.length-1

 while i < single.length-2
   new << single[i]
   i+=array.length-1
 end
 new.sum
  
    
end



p diagonal([
    [1, 2, 3],
    [4, 5, 6],
    [7, 9, 8],
]) 


 OUTPUT
 15
That is for finding the sum of right diagonal of a 2D array