有没有办法从更大的阵列/矩阵创建2 x 2阵列/矩阵

时间:2014-04-30 07:48:40

标签: ruby arrays matrix

Ruby的新手,目前正在学习。

我不确定我是否应该使用数组或矩阵。

我有阵列

[['J','O','I','J','O'],
 ['I','J','O','J','O'],
 ['I','I','J','I','J']]

我想在图片中看到以下内容。

['J', 'O']
['I', 'J'] 

enter image description here

我认为使用Ruby Matrix,但我不确定是否可以将原始数组/矩阵划分为2 x 2的小块,如果它与[J, O], [I, J]匹配。

或者我应该使用数组和循环。

我感谢任何投入。

3 个答案:

答案 0 :(得分:1)

您可以定义以下内容:

def find_in_matrix(matrix, target)
  (0..matrix.length-target.length).to_a.product(
    (0..matrix.first.length-target.first.length).to_a).select do |x, y|
    (0...target.length).to_a.product(
      (0...target.first.length).to_a).all? do |test_x, test_y|
      matrix[x+test_x][y+test_y] == target[test_x][test_y]
    end
  end
end

matrix = [["J", "O", "I", "J", "O"], 
          ["I", "J", "O", "J", "O"], 
          ["I", "I", "J", "I", "J"]]

target = [["J", "O"],
          ["I", "J"]]

find_in_matrix(matrix, target)
 => [[0, 0], [1, 1], [1, 3]] 

此解决方案简单地覆盖了matrix的{​​{1}}大小的所有子矩阵,并选择与其相等的子矩阵。

答案 1 :(得分:1)

不是直接回答问题,也不是获得匹配位置的有效方法:

matrix = [
  %w(J O I J O),
  %w(I J O J O),
  %w(I I J I J)
]

target = [
  %w(J O),
  %w(I J)
]

matrix.each_cons(target.length).each_with_index do |sub, row|
  sub.map{|a| a.each_cons(target[0].length).to_a}.tap do |sub|
    head = sub.shift
    head.zip(*sub).each_with_index do |m, col|
      if m == target
        puts "#{row}, #{col}"
      end
    end
  end
end

答案 2 :(得分:1)

我建议您使用Matrix#minor方法执行此操作。

<强>代码

require 'matrix'

def find_in_matrix(arr,sub)
  sub_nrows = sub.size
  sub_ncols = sub.first.size
  rows      = Array[*0..arr.size-sub_nrows]
  cols      = Array[*0..arr.first.size-sub_ncols]
  arr_m     = Matrix[*arr]
  sub_m     = Matrix[*sub]
  rows.product(cols).select {|i,j| arr_m.minor(i,sub_nrows,j,sub_ncols)==sub_m}
end

示例

arr = [['J','O','I','J','O'],
       ['I','J','O','J','O'],
       ['I','I','J','I','J']]

sub = [['J', 'O'],
       ['I', 'J']]

find_in_matrix(arr,sub)                    #=> [[0, 0], [1, 1], [1, 3]]
find_in_matrix(arr, [['O'], ['J']])        #=> [[0, 1], [1, 2], [1, 4]]
find_in_matrix(arr, [['O']])               #=> [[0, 1], [0, 4], [1, 2], [1, 4]]
find_in_matrix(arr, [['I','J','O']])       #=> [[0, 2], [1, 0]]
find_in_matrix(arr, [['I','J'],['J','O']]) #=> []
find_in_matrix(arr, [[]])                  #=> [[0, 0], [0, 1],...,[0, 5]] 
                                           #    [1, 0], [1, 1],...,[1, 5]]
                                           #    [2, 0], [2, 1],...,[2, 5]]

<强>解释

对于上面的示例:

sub_nrows = sub.size                              #=> 2
sub_ncols = sub.first.size                        #=> 2
rows      = Array[*0..(arr.size-sub_nrows)]       #=> [0, 1]
cols      = Array[*0..(arr.first.size-sub_ncols)] #=> [0, 1, 2, 3]
arr_m     = Matrix[*arr]
  #=> Matrix[["J", "O", "I", "J", "O"], ["I", "J", "O", "J", "O"],
  #          ["I", "I", "J", "I", "J"]]
sub_m     = Matrix[*sub]
  #=> Matrix[["J", "O"], ["I", "J"]]

a = rows.product(cols)
  #=> [[0, 0], [0, 1], [0, 2], [0, 3], [1, 0], [1, 1], [1, 2], [1, 3]]
a.select {|i,j| arr_m.minor(i,sub_nrows,j,sub_ncols)==sub_m}
  #=> [[0, 0], [1, 1], [1, 3]]

考虑a select传递到块中的第一个元素:[0, 0](即,块变量ij都被分配了值零)。因此,我们计算:

arr_m.minor(i,sub_nrows,j,sub_ncols) #=> arr_m.minor(0,2,0,2) 
  #=> Matrix[["J", "O"], ["I", "J"]]

作为

arr_m.minor(0,2,0,2) == sub_m

[0, 0]已被选中。另一方面,对于[1, 2]的元素ai => 1, j => 2,所以:

arr_m.minor(i,sub_nrows,j,sub_ncols) #=> arr_m.minor(1,2,2,2) 
  #=> Matrix[["O", "J"], ["J", "I"]]

不等于sub_m,因此未选择元素[1, 2]

请注意,Matrix#minor有两种形式。我使用了带有四个参数的表单。另一种形式将两个范围作为参数。