ruby 中的数独生成器

Sudoku generator in ruby

我正在尝试使用以下代码生成 3x3 数独,

[*1..3].permutation.uniq{
    _1.index(1) && _1.index(2) && _1.index(3)
}

我试图在 uniq 方法中传递多个条件,但我做不到。我看过他们建议的其他 SO post,

uniq{[cond1, cond2, ...]}

但是,它不起作用,我也试过||

我认为&&只取最后一个条件,而||只取第一个条件,因为它们都是真值!

如何解决?


预期输出:

3x3 sudoku like:
[1, 2, 3]
[2, 3, 1]
[3, 1, 2]

以上数独中的数字顺序无关紧要。

I'm trying to use those three parameters in uniqueness, somehow. Like, if any permutation has any number at same index, then drop that one.

我怀疑您是否可以使用 uniq 生成数独,因为该方法一次只对一个元素进行操作,而没有考虑其他元素。

您可以使用循环删除这些值。

您首先生成所有排列:(我使用 4×4 数独进行演示)

permutations = [*1..4].permutation.to_a
#=> [[1, 2, 3, 4], [1, 2, 4, 3], [1, 3, 2, 4], [1, 3, 4, 2], [1, 4, 2, 3], [1, 4, 3, 2],
#    [2, 1, 3, 4], [2, 1, 4, 3], [2, 3, 1, 4], [2, 3, 4, 1], [2, 4, 1, 3], [2, 4, 3, 1],
#    [3, 1, 2, 4], [3, 1, 4, 2], [3, 2, 1, 4], [3, 2, 4, 1], [3, 4, 1, 2], [3, 4, 2, 1],
#    [4, 1, 2, 3], [4, 1, 3, 2], [4, 2, 1, 3], [4, 2, 3, 1], [4, 3, 1, 2], [4, 3, 2, 1]]

从这个数组中,您选择一个随机元素作为第一行:

row_1 = permutations.sample #=> [3, 2, 1, 4]

然后删除所有在第一个位置具有 3,或在第二个位置具有 2,在第三个位置具有 1,或在第四个位置具有 4 的所有元素:

permutations.delete_if { |row| row_1.zip(row).any? { |i, j| i == j } }
#=> [[1, 3, 4, 2], [1, 4, 2, 3], [1, 4, 3, 2],
#    [2, 1, 4, 3], [2, 3, 4, 1], [2, 4, 3, 1],
#    [4, 1, 2, 3], [4, 1, 3, 2], [4, 3, 2, 1]]

从剩余的数组中,您可以选择另一个随机元素作为第二行并重新开始:

row_2 = permutations.sample #=> [2, 3, 4, 1]

permutations.delete_if { |row| row_2.zip(row).any? { |i, j| i == j } }
#=> [[1, 4, 2, 3], [1, 4, 3, 2],
#    [4, 1, 2, 3], [4, 1, 3, 2]]

row_3 = permutations.sample #=> [1, 4, 3, 2]

permutations.delete_if { |row| row_3.zip(row).any? { |i, j| i == j } }
#=> [[4, 1, 2, 3]]

row_4 = permutations.sample #=> [4, 1, 2, 3]   (or permutations.last)

结果 row_1row_2row_3row_4 是:(打印为数独)

╔═════╤═════╗
║ 3 2 │ 1 4 ║
║ 2 3 │ 4 1 ║
╟─────┼─────╢
║ 1 4 │ 3 2 ║
║ 4 1 │ 2 3 ║
╚═════╧═════╝

您可能会注意到,虽然行和列仅包含唯一数字,但 2×2 子网格包含重复项。因此无效.


您或许可以添加另一个考虑子网格的条件,但有更简单的方法可以生成有效的数独。这是一个:

您生成随机有效的第一行,例如:

row_1 = [*1..4].shuffle #=> [3, 4, 2, 1]

对于第二行,将第一行旋转 2:(子网格大小)

row_2 = row_1.rotate(2) #=> [2, 1, 3, 4]

对于第 3 行和第 4 行,将第一行分别旋转 1 和 3:

row_3 = row_1.rotate(1) #=> [4, 2, 1, 3]
row_4 = row_1.rotate(3) #=> [1, 3, 4, 2]

打印为数独:

╔═════╤═════╗
║ 3 4 │ 2 1 ║
║ 2 1 │ 3 4 ║
╟─────┼─────╢
║ 4 2 │ 1 3 ║
║ 1 3 │ 4 2 ║
╚═════╧═════╝