我在Ruby中编写了一个Killer Sudoku Solver,我尝试采用人工策略并将它们放入代码中。我已经实施了大约10个策略,但我对此有一个问题。
在杀手数独,我们有"区域"细胞和我们知道这些细胞的总和,我们知道每个细胞的可能性。
示例:
我希望我的程序能够尝试所有可能性以消除可能性。例如,在这里,单元格1不能为9,因为您不能通过在单元格2和3中添加两个数字来生成3。
所以我希望对于任意数量的单元格,它会通过尝试它们并看到它不起作用来删除那些不可能的单元格。
我怎样才能使这个工作?
答案 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”。有些人发现递归算法有点难以理解,所以你的里程可能会有所不同。