具有多种可能性的细胞总和

时间:2012-04-11 16:23:47

标签: ruby

我在Ruby中编写了一个Killer Sudoku Solver,我尝试采用人工策略并将它们放入代码中。我已经实施了大约10个策略,但我对此有一个问题。

在杀手数独,我们有"区域"细胞和我们知道这些细胞的总和,我们知道每个细胞的可能性。

示例:

  • 细胞1可以是1,3,4或9
  • 细胞2可以是2,4或5
  • 细胞3可以是3,4或9
  • 所有单元格的总和必须为12

我希望我的程序能够尝试所有可能性以消除可能性。例如,在这里,单元格1不能为9,因为您不能通过在单元格2和3中添加两个数字来生成3。

所以我希望对于任意数量的单元格,它会通过尝试它们并看到它不起作用来删除那些不可能的单元格。

我怎样才能使这个工作?

1 个答案:

答案 0 :(得分:1)

有多种方法可以解决游戏解决的一般问题,而模仿人类策略并不总是最好的方法。也就是说,您可以通过以下方式解决问题:

第一种方式,蛮力

基本上,我们想尝试单元组合的所有可能性,并选择具有正确总和的那些。

cell_1 = [1,3,4,9]
cell_2 = [2,4,5]
cell_3 = [3,4,9]
all_valid_combinations = cell_1.product(cell_2,cell_3).select {|combo| combo.sum == 12}
# => [[1, 2, 9], [3, 5, 4], [4, 4, 4], [4, 5, 3]]
#.sum isn't a built-in function, it's just used here for convenience

将其削减到单个细胞,你可以这样做:

cell_1 = all_valid_combinations.map {|combo| combo[0]}.uniq
# => [1, 3, 4]
cell_2 = all_valid_combinations.map {|combo| combo[1]}.uniq
# => [2, 5, 4]
. . .

如果您没有大量的单元格,这种方式更容易编码。但它可能会有点效率低下。对于小问题,这是我使用的方式。


第二种方式,回溯搜索

另一种众所周知的技术从另一种方法中解决了这个问题。基本上,对于每个细胞,问“这个细胞可以是这个数字,给定其他细胞吗?”

所以,从单元格1开始,数字是1吗?检查,我们看到单元格2和3是否可以总和为11.(12-1)   *单元格2的值是否为2?检查,可以将单元格3总和为9(11-1)

等等。在非常大的情况下,您可以有许多有效组合,这会稍快一些,因为您可以在第一次找到单元格的有效数字时返回“true”。有些人发现递归算法有点难以理解,所以你的里程可能会有所不同。