【问题标题】:Random Sudoku Generator随机数独发生器
【发布时间】:2017-06-20 21:26:07
【问题描述】:

我正在尝试构建一个 python 脚本,它生成一个 9x9 块,其编号为 1-9,沿行、列和 3x3 块内是唯一的 - 你知道,数独!

所以,我想我会从简单开始,然后越做越复杂。首先,我做了它,所以它用数字 1-9 随机填充每个数组值。然后确保没有复制沿行的数字。接下来,我想对行和列进行相同的操作。我认为我的代码还可以 - 它肯定不快,但我不知道它为什么会卡住..

import numpy as np
import random

#import pdb
#pdb.set_trace()

#Soduku solver!

#Number input

soduku = np.zeros(shape=(9,9))

for i in range(0,9,1):
    for j in range(0,9,1):
        while True:
            x = random.randint(1,9)
            if x not in soduku[i,:] and x not in soduku[:,j]:
                soduku[i,j] = x
                if j == 8: print(soduku[i,:])
                break

所以它在填充随机整数的列中移动,删除一行并重复。如果真的不走运,代码真正需要做的最多是为每个方块生成 9 个数字 - 我认为如果我们解决它,需要生成的值将少于 9*9*9。有什么东西破坏了它!

有什么想法吗?!

【问题讨论】:

  • 您是否尝试在 while 循环和 if 之外打印一些值?
  • @Prune 我认为这是可以重现问题的最小代码......它只有 11 行。
  • 您缺少“可验证”部分:这不会产生任何输出,并且您没有显示您得到的结果与您期望的结果。您还应该从解决此问题的努力中获得一些调试结果:一些战略性放置的 print 语句,如果没有其他的话。
  • @Prune 它输出数独的三到五行(大部分时间)并且它停止了,他想要的是代码完成它是微不足道的。
  • 大家好,对不起,我确实有一些打印声明。在我将它们复制粘贴到这里之前,我曾在某个时候把它们拿出来!主要原因是它们有时无法工作 - 它会冻结,当我在内核上点击 stpp 时,它会突然打印更多内容

标签: python numpy random sudoku


【解决方案1】:

我认为正在发生的事情是您的代码卡在了 while 循环中。你测试条件if x not in soduku[i,:] and x not in soduku[:,j],但是如果不满足这个条件会发生什么?很可能您的代码正在运行到一个死胡同(无法用任何值解决),并且由于永远无法满足中断条件而卡在 while 循环中。

【讨论】:

  • 是的,我觉得这就是正在发生的事情。由于某种原因,我电脑上的控制台并没有真正反映这一点,似乎它只是停止了打印,即使它被卡得更远了
  • 也许你可以尝试递归——如果我们在当前棋盘状态下到达死胡同,我们可以回溯递归树并从最后一个有效的棋盘状态继续(有解决方案的潜力)。
  • 是的!我真的很喜欢这个想法——不得不说这有点超出了我的 python 经验。我正在考虑将整个事情放在另一个while循环中,如果它卡住了(就像现在一样),它会在一个打破while循环并重复它的if语句中被识别出来?我已经看到了一些这样的例子。这是你的意思的一种简化版本吗?
  • 是的!我相信这会奏效——事实上,这可能会更快,因为您不必处理函数调用开销
【解决方案2】:

像这样生成它不太可能奏效。有很多方法可以生成 9 个 3*3 方格中的 8 个,从而根本无法填充最后一个方格,让它永远挂起。

另一种方法是填写当时所有的数字(因此,首先是所有1s,然后是所有2s,等等)。就像Eight queens puzzle,但有 9 个皇后。而当你到达一个无法放置数字的位置时,重新开始。

另一种方法是从9 开始所有方格并以某种方式策略性地递减它们,例如先把所有不能为9的都减1,不包括当前行/列/方格中的9,如果都不可能或都可能,随机减1。

你也可以尝试enumerate all sudoku boards,然后用一个随机整数反转枚举函数,但我不知道这可能有多成功,但这是唯一可以均匀随机选择它们的方法。

【讨论】:

  • 很公平,我知道这在阅读回复后不会真正起作用。皇后拼图技术明天会让我很忙!希望我可以让它工作
【解决方案3】:

你是从一个困难的方向来解决这个问题的。从一个有效的数独板开始并使用它来制作一个不同的有效数独板要容易得多。

一个简单有效的板是:

1 2 3 | 4 5 6 | 7 8 9
4 5 6 | 7 8 9 | 1 2 3
7 8 9 | 1 2 3 | 4 5 6
---------------------
2 3 4 | 5 6 7 | 8 9 1
5 6 7 | 8 9 1 | 2 3 4
8 9 1 | 2 3 4 | 5 6 7
---------------------
3 4 5 | 6 7 8 | 9 1 2
6 7 8 | 9 1 2 | 3 4 5
9 1 2 | 3 4 5 | 6 7 8

找到一个有效的棋盘后,您可以用原来的棋盘制作一个新的有效棋盘。

您可以将三个 3x3 块的任何一行与任何其他块行交换。您可以将三个 3x3 块的任何列与另一个块列交换。在每个块行中,您可以交换单个单元格行;在每个块列中,您可以交换单个单元格列。最后,您可以对数字进行置换,这样单元格中就有不同的数字,只要置换在整个棋盘上保持一致即可。

这些更改都不会使有效的板无效。

【讨论】:

    【解决方案4】:

    我使用来自 itertools 的 permutations(range(1,10)) 来创建所有可能行的列表。然后我将每一行从上到下一一放入数独。如果发生矛盾,请使用列表中的另一行。通过这种方法,我可以在短时间内找出一些有效的完整数独板。它会在一分钟内继续生成完整的电路板。

    然后我从有效的已完成数独板上随机位置一个一个地删除数字。删除每个数字后,检查它是否仍然有唯一的解决方案。如果不是,则恢复原来的号码并更改到下一个随机位置。通常我可以从板上删除 55~60 个数字。也需要一分钟内的时间。这是可行的。

    但是,前几个生成完整的数独板在第一行有数字 1,2,3,4,5,6,7,8,9。所以我洗牌整个名单。洗牌后,很难生成完整的数独板。任务失败。

    更好的方法可能是这种方式。你从互联网上收集了一些数独。您完成它们,以便将它们用作种子。如上文第 2 段所述,您从它们中删除数字。您可以获得一些数独。您可以通过以下任何一种方法使用这些数独来进一步生成更多数独

    1. 交换第 1 行和第 3 行,或第 4 行和第 6 行,或第 7 行和第 9 行
    2. 列的类似方法
    3. 将 3x3 块 1,4,7 与 3,6,9 或 1,2,3 与 7,8,9 对应地交换。
    4. 垂直或水平镜像数独
    5. 数独旋转 90、180、270
    6. 随机排列板上的数字。例如,1->2, 2->3, 3->4, .... 8->9, 9->1。或者你可以只交换其中的 2 个。例如。 1->2、2->1。这也有效。

    【讨论】:

      猜你喜欢
      • 2011-01-23
      • 2010-12-30
      • 2019-12-15
      相关资源
      最近更新 更多