【问题标题】:Two-dimensional subarrays (a smaller square out of a larger square)二维子阵列(较大正方形中的较小正方形)
【发布时间】:2015-09-26 09:51:38
【问题描述】:

主要问题:您可以轻松地从数组中获取子数组,例如子 = a[2, 3]。但是如果你有一个二维数组,你怎么能得到一个二维子数组呢?

实例: 我正在尝试遍历数独板中的 9 个 3x3 方格,以检查每个 3x3 方格中的重复数字。

如果我有一个由 9 个数组(行)组成的数组(板),是否有一种简单的方法可以获得板的 3x3 子 2D 数组?有没有一种简单的方法可以遍历所有 9 个 3x3 子 2D 数组?

编辑:对不起,如果原文不清楚,主要是获取2D数组的一部分的原理,数独部分更多是该原理的应用。

【问题讨论】:

  • 您确实需要澄清您的问题(通过编辑),以阻止(并可能扭转)反对意见,并为将来阅读它的 SO 成员谋福利。您需要清楚而准确地陈述您的问题,这现在是隐含的和模糊的(因此是反对票)。我认为问题是,“给定一个由数组solution 表示的数独解决方案,这样solution[i][j] 是行i+1、列j+1(行1 到@987654326)中的条目(整数或字符串) @,列19),我如何确定九个 3x3 块中的任何一个是否包含重复条目?
  • 是的,@Mirror318 你是想验证一个谜题是否已经解决,还是只是想显示一个待解决的谜题?
  • 您好!你好!有人在家吗?

标签: arrays ruby multidimensional-array


【解决方案1】:

您可以按如下方式确定数独解决方案是否有效。使用 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)

【讨论】:

    【解决方案2】:

    我不明白你为什么会有行,这会使事情变得复杂。

    我建议你简单地拥有一个长度为 81 的数组 a。给定一个元素的索引 i,你可以假设它所属的行、列或子方格的开始元素,其索引给出为:

    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]}

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-31
      • 2011-12-06
      相关资源
      最近更新 更多