Coordinates conversion according the matrix shape
I would like to convert an index in a flattened array into a coordinate in a multi-dimension array.
Example: In the following 2-dimension array whose size is [3, 3]:
[
[ -, -, - ],
[ *, -, - ],
[ -, -, - ]
]
the coordinate of *
is [0, 1]. If we flatten this array as:
[ -, -, -, *, -开发者_运维技巧, -, -, -, - ]
coordinate (or the index) of *
becomes 3. How can we do the opposite? That is, a method like:
index_to_coordinates([3, 3], 3) # => [0, 1]
Notice that your index_to_coordinates
takes [3, 3]
(in addition to the flattened index 3
) as an argument, but that is redundant. The information you need is that each line in the matrix is of length 3
, and that the flattened index is 3
.
3.divmod(3).reverse # => [0, 1]
divmod
gives you a pair the quotient and the remainder. Since you are expecting the order: x-coordinate (remainder) then y-coordinate (quotient), you need reverse
to flip the order.
Edited according to change in the question
Note: I assume ruby 1.9 in the following. I do not want to bother with ruby 1.8. If necessary, please translate it to ruby 1.8 on your own. It should be easy.
Suppose you have a structure:
[
[
[0, 1, 2, 3]
[4, 5, 6, 7]
[8, 9, 10, 11]
]
[
[12, 13, 14, 15]
[16, 17, 18, 19]
[20, 21, 22, 23]
]
]
so that the size of this structure is represented as [2, 3, 4]. In general, we can express the size as an array sizes
. You can convert this into an array flattened
that represents the size of each dimension when the whole structure is flattened upto that dimension:
flattened = sizes.dup.drop(1)
(1...flattened.length).reverse_each{|i| flattened[i-1] *= flattened[i]}
With the particular example:
flattened # => [12, 4]
This means that the largest cycle is 12, the next is 4. Suppose you want the coordinate of 7
. In order to get that, you do:
index = 7
coordinate = flattened.each_with_object([]) do |size, array|
quotient, index = index.divmod(size)
array.push(quotient)
end
coordinate.push(index)
This will give you:
coordinate # => [0, 1, 3]
精彩评论