Добавить диагональную разницу матрицы - PullRequest
0 голосов
/ 26 апреля 2018

Проблема разности диагоналей HackerRank.

Выведите абсолютную разницу между суммами двух диагоналей матрицы в виде одного целого числа.

Ссылка на проблему: https://www.hackerrank.com/challenges/diagonal-difference/problem

Я часами пытался решить эту проблему в Ruby. Я наткнулся на ответ, который кто-то другой понял.

Теперь я прошу помощи в понимании того, как работает этот метод. Я хочу понять, что он делает. Меня смущает весь цикл.

a.each_with_index do |array, index|
  left_right += array[index]
  right_left += array[-index-1]

Может кто-нибудь объяснить, что происходит в этом блоке кода, чтобы я мог изучить и лучше понять Ruby? Спасибо.

def diagonalDifference(a)
  left_right=0
  right_left=0
  a.each_with_index do |array, index|
    left_right += array[index]
    right_left += array[-index-1]
  end
  v = right_left - left_right
  return v.abs
end

Ответы [ 4 ]

0 голосов
/ 26 апреля 2018

Диагональ главной косой (или основная вторичная диагональ ) матрицы nxn a состоит из элементов a[n-1][0], a[n-2][1], ... , a[1][n-2], a[0][n-1]].

Часть проблемы заключается в том, что переменным не были даны описательные имена. Я написал бы это следующим образом.

def diagonal_difference(arr)
  main_diagonal_sum=0
  main_skew_diagonal_sum=0
  arr.each_with_index do |row, i|
    main_diagonal_sum += row[i]
    main_skew_diagonal_sum += row[-i-1]
  end
  (main_diagonal_sum - main_skew_diagonal_sum).abs
end

Я ожидаю, что row[-i-1] может быть самой запутанной частью кода. Предположим, что i = 0, затем row[-0-1] #=> row[-1], что является последним элементом row. Когда i = 1, row[-1-1] #=> row[-2], который является ближайшим к последнему элементу row, и так далее. Вместо этого можно было бы написать row[row.size-i-1].

Примечание return не требуется, если, как здесь, возвращаемое значение последнего выполненного оператора (до возврата метода) должно быть возвращено методом.

Давайте добавим несколько puts операторов в метод и проработаем пример.

def diagonal_difference(arr)
  puts "arr=#{arr}"
  main_diagonal_sum=0
  main_skew_diagonal_sum=0
  arr.each_with_index do |row, i|
    puts "row=#{row}, i=#{i}"
    main_diagonal_sum += row[i]
    puts "  row[#{i}]=#{row[i]}, main_diagonal_sum=#{main_diagonal_sum}"
    main_skew_diagonal_sum += row[-i-1]
    puts "  row[-#{i}-1]=#{row[-i-1]}, main_skew_diagonal_sum=#{main_skew_diagonal_sum}"
  end
  (main_diagonal_sum - main_skew_diagonal_sum).abs
end

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

Основная диагональная сумма равна 1+5+7 #=> 13, а основная косая диагональная сумма равна 3+5+9 #=> 17, поэтому мы ожидаем, что метод вернет (13-17).abs #=> 4.

diagonal_difference(arr)
  #=> 4

печатает следующее.

arr=[[1, 2, 3], [4, 5, 6], [9, 8, 7]]
row=[1, 2, 3], i=0
  row[0]=1, main_diagonal_sum=1
  row[-0-1]=3, main_skew_diagonal_sum=3
row=[4, 5, 6], i=1
  row[1]=5, main_diagonal_sum=6
  row[-1-1]=5, main_skew_diagonal_sum=8
row=[9, 8, 7], i=2
  row[2]=7, main_diagonal_sum=13
  row[-2-1]=9, main_skew_diagonal_sum=17

Использование метода Matrix # trace (расширенный)

Сумма элементов на двух диагоналях может быть альтернативно вычислена с использованием метода Matrix#trace и вспомогательного метода roll (как при повороте массива против часовой стрелки на 90 градусов), который преобразует диагональ основного перекоса в основную. диагонали.

def roll(arr)
  arr.map(&:reverse).transpose
end

roll(arr)
  #=> [[3, 6, 7],
  #    [2, 5, 8],
  #    [1, 4, 9]]

Это позволяет нам написать следующее.

require 'matrix'
(Matrix[*arr].trace - Matrix[*roll(arr)].trace).abs
  #=> 4
0 голосов
/ 26 апреля 2018

Sidenote: NB Я публикую это как ответ, а не комментарий, для форматирования; это не должно быть проголосовано.

Более рубиновая идиоматическая версия фрагмента, которую вы разместили, будет:

def diagonal_difference(a)
  a.each.with_object([0, 0]).with_index do |(e, left_right), idx|
    left_right[0] += array[idx]
    right_left[1] += array[-idx-1]
  end.reduce(:-).abs
end
0 голосов
/ 26 апреля 2018

Вы можете использовать матричную библиотеку , как предложено в этом ответе .

require 'matrix'
(Matrix[*arr].tr - Matrix[*arr.reverse].tr).abs

Где arr - это массив глубины 2 с длиной n, а каждый подмассив также имеет длину n, например. [[a,b],[c,d]].

0 голосов
/ 26 апреля 2018

см. Далее

11 2 4
4 5 6
10 8 -12
So, a = [ [11, 2, 4], [4, 5, 6], [10, 8, -12] ]

Теперь ref each_with_index метод для a.each_with_index do |array, index|. во время первой итерации array will be [11, 2, 4] & index will be 0. array[0] = 11 & array[-0-1] i.e. array[-1] = 4 Аналогично для второй итерации array[1] = 5 & array[-1-1] i.e. array[-2] = 5 и т. Д.

Вы получите

2.3.1 :360 > left_right # 11 + 5 - 12
 => 4 
2.3.1 :361 > right_left # 4 + 5 + 10
 => 19 
2.3.1 :362 > v = right_left - left_right
 => 15 

v.abs используется для возврата абсолютной разницы в случае v is negative, Ref abs метод Numeric класса.

Примечание: - return ключевое слово необязательно, если это последняя строка без комментариев в методе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...