ruby - 在二维数组中查找相邻项

标签 ruby

我有一个这样的二维数组。

[
  ["+", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "+"], 
  ["|", "*", "*", " ", " ", "*", " ", " ", " ", " ", "*", "*", "*", "*", "*", "*", "*", "*", " ", "*", " ", "|"], 
  ["|", " ", "*", "*", "*", "*", " ", " ", " ", " ", "*", "*", " ", " ", "*", "*", " ", "*", " ", "*", " ", "|"], 
  ["|", "*", " ", "*", " ", " ", " ", " ", "*", " ", "*", " ", "*", "*", "*", " ", "*", "*", "*", " ", "*", "|"], 
  ["|", "*", "*", " ", " ", "*", " ", " ", "*", "*", "*", " ", "*", " ", "*", "*", " ", "*", "*", " ", " ", "|"], 
  ["|", "*", " ", " ", " ", "*", " ", "*", " ", " ", " ", "*", "*", "*", "*", "*", " ", " ", " ", "*", "*", "|"], 
  ["|", " ", " ", " ", " ", " ", "*", " ", "*", " ", " ", " ", "*", " ", " ", " ", " ", " ", "*", " ", " ", "|"], 
  ["|", "*", "*", " ", "*", "*", "*", " ", "*", " ", " ", "*", "*", "*", "*", " ", "*", " ", " ", "*", " ", "|"], 
  ["|", " ", "*", " ", "*", "*", "*", "*", " ", " ", " ", "*", "*", " ", " ", " ", " ", "*", " ", "*", "*", "|"], 
  ["|", " ", "*", " ", " ", "*", " ", " ", "*", " ", "*", "*", "*", " ", "*", " ", "*", " ", " ", " ", "*", "|"], 
  ["|", " ", "*", "*", "*", "*", " ", " ", " ", " ", "*", "*", " ", "*", "*", "*", " ", " ", " ", "*", "*", "|"], 
  ["|", " ", " ", "*", "*", " ", "*", "*", "*", " ", " ", " ", " ", " ", " ", "*", "*", " ", " ", " ", " ", "|"], 
  ["|", "*", " ", "*", "*", " ", "*", " ", "*", "*", " ", " ", " ", "*", " ", "*", "*", "*", " ", " ", " ", "|"], 
  ["|", " ", " ", " ", "*", " ", "*", " ", "*", " ", "*", " ", " ", " ", " ", " ", " ", "*", "*", " ", " ", "|"], 
  ["|", "*", " ", "*", " ", "*", " ", "*", " ", " ", " ", "*", " ", "*", "*", " ", "*", "*", "*", "*", "*", "|"], 
  ["|", " ", " ", " ", "*", " ", "*", "*", "*", "*", "*", "*", " ", " ", "*", " ", " ", "*", "*", " ", "*", "|"], 
  ["|", "*", "*", "*", "*", "*", " ", " ", " ", "*", " ", "*", " ", "*", "*", " ", "*", "*", " ", " ", "*", "|"], 
  ["|", "*", " ", " ", " ", "*", "*", "*", "*", " ", " ", "*", " ", "*", " ", "*", " ", "*", " ", "*", "*", "|"], 
  ["|", "*", " ", "*", "*", "*", "*", "*", "*", " ", "*", "*", "*", "*", " ", " ", " ", "*", " ", " ", " ", "|"], 
  ["|", " ", " ", "*", " ", " ", "*", "*", " ", " ", " ", "*", " ", "*", "*", " ", " ", " ", " ", " ", "*", "|"], 
  ["|", " ", "*", " ", " ", " ", "*", "*", "*", "*", "*", "*", "*", "*", "*", "*", "*", " ", " ", " ", "*", "|"], 
  ["+", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "+"]
]

我需要找到每个“*”附近的炸弹数量,如下图所示。

enter image description here

我这样做是为了获取索引,但我不知道如何获取相邻元素。

@array_map.each_index do |i|
subarray = @array_map[i]
 subarray.each_index do |x|
    puts String(i) << " " << String(x) << "... " << @array_map[i][x]
 end
end

最佳答案

minefield = [
  ["+", "-", "-", "-", "-", "-", "-", "-"],
  ["|", "*", "*", " ", " ", "*", " ", " "],
  ["|", " ", "*", "*", "*", "*", " ", " "],
  ["|", "*", " ", "*", " ", " ", " ", " "],
  ["|", "*", "*", " ", " ", "*", " ", " "],
  ["|", "*", " ", " ", " ", "*", " ", "*"],
  ["|", " ", " ", " ", " ", " ", "*", " "]
]
last_row = minefield.size-1
  #=> 6
last_col = minefield.first.size-1
  #=> 7
adj_cols = (0..last_col).each_with_object({}) do |j,h|
  h[j] = ([j-1, 0].max..[j+1, last_col].min).to_a
end
  #=> {0=>[0, 1], 1=>[0, 1, 2], 2=>[1, 2, 3], 3=>[2, 3, 4], 4=>[3, 4, 5],
  #    5=>[4, 5, 6], 6=>[5, 6, 7], 7=>[6, 7]}
arr = (0..last_row).each_with_object(minefield.dup.map(&:dup)) do |i,a|
  adj_rows = ([i-1, 0].max..[i+1, last_row].min).to_a
  (0..last_col).each do |j|
    next unless a[i][j] == ' '
    a[i][j] = adj_rows.product(adj_cols[j]).count do |r,c|
      minefield[r][c] == '*'
    end.to_s
  end
end
arr.each { |row| p row }

显示

["+", "-", "-", "-", "-", "-", "-", "-"]
["|", "*", "*", "4", "4", "*", "2", "0"]
["|", "4", "*", "*", "*", "*", "2", "0"]
["|", "*", "6", "*", "5", "3", "2", "0"]
["|", "*", "*", "2", "3", "*", "3", "1"]
["|", "*", "3", "1", "2", "*", "4", "*"]
["|", "1", "1", "0", "1", "2", "*", "2"]

参见 Array#product . adj_cols 是一个散列,它给出了一个列索引数组,用于标识每个列索引的相邻位置。在开始时执行一次而不是对 minefield 的每个元素(行)重复计算是有意义的。

要返回的数组初始化为

minefield.dup.map(&:dup)  

这样雷区就不会被突变(修改)。

这是一个示例计算。

i = 3
adj_rows = ([i-1, 0].max..[i+1, last_row].min).to_a
  #=> ([2, 0].max..[4, 6].min).to_a
  #=> (2..4).to_a
  #=> [2, 3, 4]   
j = 4
a = adj_cols[j]
  #=> [3, 4, 5]
b = adj_rows.product(a)
  #=> [[2, 3], [2, 4], [2, 5],
  #    [3, 3], [3, 4], [3, 5],
  #    [4, 3], [4, 4], [4, 5]] 
b.count { |r,c| minefield[r][c] == '*' }
  #=> 5

请注意,b 包括 [3, 4],我们知道它等于 ' '。将它留在 count 操作中并没有什么坏处,但是,因为 minefield[r][c] == '*' #=> false)。我们也可以这样写:

b = adj_rows.product(a) - [[i, j]]
  #=> [[2, 3], [2, 4], [2, 5],
  #    [3, 3],         [3, 5],
  #    [4, 3], [4, 4], [4, 5]] 

这是第二个示例(如果 minefield[0][4] #=> ' ' 将适用)。

i = 0
j = 4
adj_rows = ([i-1, 0].max..[i+1, last_row].min).to_a
  #=> [0, 1]   
j = 4
a = adj_cols[j]
  #=> [3, 4, 5]
b = adj_rows.product(a)
  #=> [[0, 3], [0, 4], [0, 5],
  #    [1, 3], [1, 4], [1, 5]] 

对于题中给出的minefield数组,返回值如下。

["+", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "+"]
["|", "*", "*", "4", "4", "*", "2", "0", "0", "2", "*", "*", "*", "*", "*", "*", "*", "*", "4", "*", "2", "|"]
["|", "4", "*", "*", "*", "*", "2", "1", "1", "4", "*", "*", "6", "7", "*", "*", "7", "*", "6", "*", "3", "|"]
["|", "*", "6", "*", "5", "3", "2", "2", "*", "6", "*", "6", "*", "*", "*", "6", "*", "*", "*", "4", "*", "|"]
["|", "*", "*", "2", "3", "*", "3", "3", "*", "*", "*", "6", "*", "8", "*", "*", "5", "*", "*", "5", "3", "|"]
["|", "*", "3", "1", "2", "*", "4", "*", "4", "4", "3", "*", "*", "*", "*", "*", "3", "3", "4", "*", "*", "|"]
["|", "3", "3", "2", "3", "5", "*", "5", "*", "2", "2", "5", "*", "7", "5", "4", "2", "2", "*", "4", "3", "|"]
["|", "*", "*", "4", "*", "*", "*", "6", "*", "2", "2", "*", "*", "*", "*", "2", "*", "3", "4", "*", "3", "|"]
["|", "4", "*", "5", "*", "*", "*", "*", "3", "3", "4", "*", "*", "6", "3", "4", "3", "*", "3", "*", "*", "|"]
["|", "3", "*", "6", "6", "*", "5", "3", "*", "3", "*", "*", "*", "5", "*", "4", "*", "2", "3", "5", "*", "|"]
["|", "2", "*", "*", "*", "*", "4", "4", "3", "4", "*", "*", "4", "*", "*", "*", "4", "2", "1", "*", "*", "|"]
["|", "2", "5", "*", "*", "6", "*", "*", "*", "4", "3", "2", "3", "3", "6", "*", "*", "3", "2", "2", "2", "|"]
["|", "*", "3", "*", "*", "6", "*", "7", "*", "*", "2", "1", "1", "*", "3", "*", "*", "*", "3", "1", "0", "|"]
["|", "2", "4", "4", "*", "5", "*", "5", "*", "4", "*", "2", "3", "3", "4", "4", "6", "*", "*", "4", "2", "|"]
["|", "*", "2", "*", "4", "*", "5", "*", "5", "5", "5", "*", "3", "*", "*", "3", "*", "*", "*", "*", "*", "|"]
["|", "3", "5", "5", "*", "5", "*", "*", "*", "*", "*", "*", "5", "5", "*", "5", "5", "*", "*", "6", "*", "|"]
["|", "*", "*", "*", "*", "*", "6", "6", "6", "*", "6", "*", "5", "*", "*", "4", "*", "*", "5", "5", "*", "|"]
["|", "*", "6", "5", "7", "*", "*", "*", "*", "4", "5", "*", "7", "*", "5", "*", "5", "*", "4", "*", "*", "|"]
["|", "*", "4", "*", "*", "*", "*", "*", "*", "3", "*", "*", "*", "*", "5", "2", "3", "*", "3", "3", "3", "|"]
["|", "2", "4", "*", "4", "5", "*", "*", "6", "5", "6", "*", "8", "*", "*", "4", "3", "2", "1", "2", "*", "|"]
["|", "1", "*", "2", "1", "2", "*", "*", "*", "*", "*", "*", "*", "*", "*", "*", "*", "1", "0", "2", "*", "|"]
["+", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "+"]

关于ruby - 在二维数组中查找相邻项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65402301/

相关文章:

ruby - 仅适用于 cron :/usr/bin/env: ruby_executable_hooks: No such file or directory

ruby - 设置 RSpec 测试的顺序

mysql - 无法在 Mac OS X 上安装 mysql gem

ruby-on-rails - 使用 CSV 库时流关闭 IO 错误

ruby-on-rails - NameError - 运行开发服务器时未初始化常量

ruby - Rake cp 权限在 Windows 上被拒绝

sql-server - ActiveRecord(无 Rails): How to configure a connection to an azure database

ruby - 我将如何编写语法检查器?

ruby-on-rails - 在 Rails 应用程序上运行 ruby​​ 时出现问题

ruby-on-rails - 如何查看通过 Rails 应用程序发送的 HTTP 请求?