主要问题:您可以轻松地从数组中获取子数组,例如sub = a [2,3]。但是如果你有一个2D数组,你怎么能得到一个2D子阵列?
实际例子: 我试图在数独板上迭代9个3x3方块,检查每个3x3方块的重复数字。
如果我有一个9个阵列(行)的阵列(板),有没有一种简单的方法来获得3x3子2D阵列的电路板?有没有一种简单的方法可以通过所有9个3x3子2D阵列?
编辑:对不起,如果原件不清楚,主要的是获取2D阵列的一部分的原则,数独部分更多的是原理的应用。
答案 0 :(得分:2)
您可以确定Sudoku解决方案是否有效,如下所示。使用方法Array#minor简化了检查3x3块。
<强>代码强>
require 'matrix'
def valid?(soln)
rows_invalid = invalid_rows?(soln, "rows")
cols_invalid = invalid_rows?(soln.transpose, "columns")
blocks_invalid = invalid_blocks?(soln)
puts "Solution is valid" unless rows_invalid || cols_invalid || blocks_invalid
end
def invalid_rows?(soln, label)
rows_with_dups = soln.each.with_index(1).select { |r,i| r.uniq.size < r.size }
return false if rows_with_dups.empty?
puts "Duplicates are in #{label}: #{ rows_with_dups.map(&:last).join(' ') }"
return true
end
def invalid_blocks?(soln)
m = Matrix[*soln]
blocks_with_dups = [1,2,3].product([1,2,3]).select do |row,col|
f_row, f_col = 3*(row-1), 3*(col-1)
block = m.minor(f_row..(f_row+2), f_col..(f_col+2)).to_a.flatten
block.uniq.size < block.size
end
return false if blocks_with_dups.empty?
puts "Duplicates are in blocks: #{ blocks_with_dups.map { |row,col|
"(#{row}, #{col})" }.join(' ') }"
return true
end
<强>实施例强>
soln = [
%w| 4 1 7 8 5 3 9 6 2 |,
%w| 5 8 9 7 6 2 4 3 1 |,
%w| 6 3 2 9 1 4 7 5 8 |,
%w| 9 6 8 3 2 1 5 7 4 |,
%w| 7 2 3 4 8 5 1 9 6 |,
%w| 1 5 4 6 7 9 8 2 3 |,
%w| 8 4 6 2 9 7 3 1 5 |,
%w| 2 7 1 5 3 8 6 4 9 |,
%w| 3 9 5 1 4 6 2 8 7 |,
]
#=> [["4", "1", "7", "8", "5", "3", "9", "6", "2"],
# ["5", "8", "9", "7", "6", "2", "4", "3", "1"],
# ["6", "3", "2", "9", "1", "4", "7", "5", "8"],
# ["9", "6", "8", "3", "2", "1", "5", "7", "4"],
# ["7", "2", "3", "4", "8", "5", "1", "9", "6"],
# ["1", "5", "4", "6", "7", "9", "8", "2", "3"],
# ["8", "4", "6", "2", "9", "7", "3", "1", "5"],
# ["2", "7", "1", "5", "3", "8", "6", "4", "9"],
# ["3", "9", "5", "1", "4", "6", "2", "8", "7"]]
valid?(soln)
#=> "Solution is valid"
现在更改soln
中的两个元素:
soln[0][5] = "7"
soln[8][8] = "3"
soln.map { |row| row.join(' ') }
#=> ["4 1 7 8 5 7 9 6 2",
# "5 8 9 7 6 2 4 3 1",
# "6 3 2 9 1 4 7 5 8",
# "9 6 8 3 2 1 5 7 4",
# "7 2 3 4 8 5 1 9 6",
# "1 5 4 6 7 9 8 2 3",
# "8 4 6 2 9 7 3 1 5",
# "2 7 1 5 3 8 6 4 9",
# "3 9 5 1 4 6 2 8 3"]
valid?(soln)
#=> Duplicates are in rows: 1 9
# Duplicates are in columns: 6 9
# Duplicates are in blocks: (1, 2) (3, 3)
答案 1 :(得分:0)
我不明白为什么你有行,这会让它变得复杂。
我建议您只使用长度为81的数组a
。给定元素的索引i
,您可以假设它所属的行,列或子方的开头元素to,其索引为:
start_of_row = (i / 9) * 9
start_of_column = i % 9
start_of_sub_square = (i / 27) * 27 + (i % 9 / 3) * 3
然后,给定起始索引j
,您可以按如下方式遍历行,列,子方格:
row_indice = [0, 1, 2, 3, 4, 5, 6, 7, 8]
column_indice = [0, 9, 18, 27, 36, 45, 54, 63, 72]
sub_square_indice = [0, 1, 2, 9, 10, 11, 18, 19, 20]
row_indice.each{|k| a[j + k]}
column_indice.each{|k| a[j + k]}
sub_square_indice.each{|k| a[j + k]}