I was trying some problems with my 2D ruby array and my LOC reduces a lot when I do array slicing. So for example,
require "test/unit"
class LibraryTest < Test::Unit::TestCase
def test_box
array = [[1,2,3,4],[3,4,5,6], [5,6,7,8], [2,3,4,5]]
puts array[1][2..3] # 5, 6
puts array[1..2][1] # 5, 6, 7, 8
end
end
I want to know if there is a way to get a diagonal slice? Lets say I want to start at [0,0] and want a diagonal slice of 3. Then I would get elements from [0,0], [1,1], [2,2] and I will get an array like [1,4,7] for example above. Is there any magic one-liner ruby code that can achieve this? 3.times do {some magic stuff?}
puts (0..2).collect { |i| array[i][i] }
Better might be a one-liner that utilizes the Matrix library:
require 'matrix'
Matrix.rows(array).each(:diagonal).to_a
I'm picking up @Shai's answer and propose to make it more functional.
First we initialize the array:
arr = [[1, 2, 3, 4], [3, 4, 5, 6], [5, 6, 7, 8], [2, 3, 4, 5]]
Then we prepare the array which serves as padding:
padding = [*0..(arr.length - 1)].map { |i| [nil] * i }
=> [[], [nil], [nil, nil], [nil, nil, nil]]
Then we apply the padding to the array. If you reverse the first usage of the padding or the second one depends if you want to get downward or upward diagonals.
padded = padding.reverse.zip(arr).zip(padding).map(&:flatten)
=> [[nil, nil, nil, 1, 2, 3, 4], [nil, nil, 3, 4, 5, 6, nil], [nil, 5, 6, 7, 8, nil, nil], [2, 3, 4, 5, nil, nil, nil]]
Then we transpose as in @Shai's solution:
padded.transpose.map(&:compact)
=> [[2], [5, 3], [3, 6, 4], [1, 4, 7, 5], [2, 5, 8], [3, 6], [4]]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With