我有一个像这样的二维数组。
[
["+", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "+"],
["|", "*", "*", " ", " ", "*", " ", " ", " ", " ", "*", "*", "*", "*", "*", "*", "*", "*", " ", "*", " ", "|"],
["|", " ", "*", "*", "*", "*", " ", " ", " ", " ", "*", "*", " ", " ", "*", "*", " ", "*", " ", "*", " ", "|"],
["|", "*", " ", "*", " ", " ", " ", " ", "*", " ", "*", " ", "*", "*", "*", " ", "*", "*", "*", " ", "*", "|"],
["|", "*", "*", " ", " ", "*", " ", " ", "*", "*", "*", " ", "*", " ", "*", "*", " ", "*", "*", " ", " ", "|"],
["|", "*", " ", " ", " ", "*", " ", "*", " ", " ", " ", "*", "*", "*", "*", "*", " ", " ", " ", "*", "*", "|"],
["|", " ", " ", " ", " ", " ", "*", " ", "*", " ", " ", " ", "*", " ", " ", " ", " ", " ", "*", " ", " ", "|"],
["|", "*", "*", " ", "*", "*", "*", " ", "*", " ", " ", "*", "*", "*", "*", " ", "*", " ", " ", "*", " ", "|"],
["|", " ", "*", " ", "*", "*", "*", "*", " ", " ", " ", "*", "*", " ", " ", " ", " ", "*", " ", "*", "*", "|"],
["|", " ", "*", " ", " ", "*", " ", " ", "*", " ", "*", "*", "*", " ", "*", " ", "*", " ", " ", " ", "*", "|"],
["|", " ", "*", "*", "*", "*", " ", " ", " ", " ", "*", "*", " ", "*", "*", "*", " ", " ", " ", "*", "*", "|"],
["|", " ", " ", "*", "*", " ", "*", "*", "*", " ", " ", " ", " ", " ", " ", "*", "*", " ", " ", " ", " ", "|"],
["|", "*", " ", "*", "*", " ", "*", " ", "*", "*", " ", " ", " ", "*", " ", "*", "*", "*", " ", " ", " ", "|"],
["|", " ", " ", " ", "*", " ", "*", " ", "*", " ", "*", " ", " ", " ", " ", " ", " ", "*", "*", " ", " ", "|"],
["|", "*", " ", "*", " ", "*", " ", "*", " ", " ", " ", "*", " ", "*", "*", " ", "*", "*", "*", "*", "*", "|"],
["|", " ", " ", " ", "*", " ", "*", "*", "*", "*", "*", "*", " ", " ", "*", " ", " ", "*", "*", " ", "*", "|"],
["|", "*", "*", "*", "*", "*", " ", " ", " ", "*", " ", "*", " ", "*", "*", " ", "*", "*", " ", " ", "*", "|"],
["|", "*", " ", " ", " ", "*", "*", "*", "*", " ", " ", "*", " ", "*", " ", "*", " ", "*", " ", "*", "*", "|"],
["|", "*", " ", "*", "*", "*", "*", "*", "*", " ", "*", "*", "*", "*", " ", " ", " ", "*", " ", " ", " ", "|"],
["|", " ", " ", "*", " ", " ", "*", "*", " ", " ", " ", "*", " ", "*", "*", " ", " ", " ", " ", " ", "*", "|"],
["|", " ", "*", " ", " ", " ", "*", "*", "*", "*", "*", "*", "*", "*", "*", "*", "*", " ", " ", " ", "*", "|"],
["+", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "+"]
]
我需要找到每个“*”附近的炸弹数量,如下图所示。
我这样做是为了获取索引,但我不知道如何获取相邻索引。
@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"]
参见数组#产品。
adj_cols
是一个哈希,它提供列索引数组来标识每个列索引的相邻位置。在开始时执行一次此操作是有意义的,而不是对 minefield
的每个元素(行)重复计算。
要返回的数组被初始化为
minefield.dup.map(&:dup)
这样
minefield
就不会被突变(修改)。
这是一个计算示例。
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", "*", "|"]
["+", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "+"]
这会起作用:
minefield = [
["+", "-", "-", "-", "-", "-", "+"],
["|", "*", "*", "*", "*", "*", "|"],
["|", "*", " ", "*", "*", " ", "|"],
["|", " ", " ", " ", "*", " ", "|"],
["|", "*", " ", "*", "*", "*", "|"],
["|", "*", "*", "*", " ", " ", "|"],
["+", "-", "-", "-", "-", "-", "+"]
]
minefield.each_with_index do |row, y|
row.each_with_index do |item, x|
next unless item == '*'
(y - 1).upto(y + 1) do |j|
(x - 1).upto(x + 1) do |i|
next if minefield[j][i] =~ /[*|+-]/
minefield[j][i] = minefield[j][i].to_i.succ.to_s
end
end
end
end
它穿过雷区阵列,跳过除炸弹之外的所有东西(
next unless item == '*'
)。一旦遇到炸弹,我们就会遍历它的周围环境,跳过任何特殊字段,例如 *
、|
、+
或 -
。 (这也会跳过炸弹本身)
由于炸弹不会出现在雷区边界,我们可以省略边界检查。
对于其余的周围字段(即空格和数字字符串),我们将该字段转换为整数(因此
" "
变为 0
),添加 1(通过 succ
),将其转换回字符串并重新分配到字段:(succ
也适用于字符串,但无论如何我们都必须处理" "
)
# blank # numeric
minefield[j][i] #=> " " # "1"
.to_i #=> 0 # 1
.succ #=> 1 # 2
.to_s #=> "1" # "2"
最后,空白字段已被炸弹计数替换:
[
["+", "-", "-", "-", "-", "-", "+"],
["|", "*", "*", "*", "*", "*", "|"],
["|", "*", "5", "*", "*", "4", "|"],
["|", "2", "4", "5", "*", "4", "|"],
["|", "*", "5", "*", "*", "*", "|"],
["|", "*", "*", "*", "4", "2", "|"],
["+", "-", "-", "-", "-", "-", "+"]
]