因为循环卡在Python中

时间:2015-01-15 18:20:03

标签: python cycle

下面的代码卡在随机点上:

import functions
from itertools import product
from random import randrange

values = {}
tables = {}
letters = "abcdefghi"
nums = "123456789"
for x in product(letters, nums): #unnecessary
    values[x[0] + x[1]] = 0
for x in product(nums, letters): #unnecessary
    tables[x[0] + x[1]] = 0

for line_cnt in range(1,10):
    for column_cnt in range(1,10):
        num = randrange(1,10)
        table_cnt = functions.which_table(line_cnt, column_cnt) #Returns a number identifying the table considered
        #gets the values already in the line and column and table considered
        line = [y for x,y in values.items() if x.startswith(letters[line_cnt-1])]
        column = [y for x,y in values.items() if x.endswith(nums[column_cnt-1])]
        table = [x for x,y in tables.items() if x.startswith(str(table_cnt))]
        #if num is not contained in any of these then it's acceptable, otherwise find another number 
        while num in line or num in column or num in table:
            num = randrange(1,10)
        values[letters[line_cnt-1] + nums[column_cnt-1]] = num #Assign the number to the values dictionary
        print(line_cnt) #debug
print(sorted(values)) #debug

正如您所看到的,它是一个使用2个词典生成随机数据方案的程序:包含完整方案的值和包含每个表的值的表。

示例:

5th square on the first line = 3
    |
    v
values["a5"] = 3
tables["2b"] = 3

那么问题是什么?我错过了什么吗?

1 个答案:

答案 0 :(得分:2)

import functions
...
        table_cnt = functions.which_table(line_cnt, column_cnt) #Returns a number identifying the table considered

当我们可以在我们自己的计算机上执行代码来测试它时,这很好。换句话说,替换" table_cnt"会很好。对于示例,使用固定值(此处,简单的字符串就足够了)。

for x in product(letters, nums):
    values[x[0] + x[1]] = 0

不是那么重要,但这更优雅:

values = {x+y: 0 for x, y in product(letters, nums)}

现在,问题的核心是:

while num in line or num in column or num in table:
    num = randrange(1,10)

这是你永远循环的地方。所以,你试图生成一个随机的数独。从您的代码中,您将生成随机列表:

nums = []
for _ in range(9):
    num = randrange(1, 10)
    while num in nums:
        num = randrange(1, 10)
    nums.append(num)

这种方法的问题在于你不知道程序需要多长时间才能完成。可能需要一秒钟或一年(但是,不太可能)。这是因为无法保证程序不会一遍又一遍地选择已经采用的数字。

尽管如此,在实践中它仍然需要相对较短的时间才能完成(这种方法效率不高但列表很短)。但是,在数独的情况下,您可能最终处于不可能的设置。例如:

line = [6, 9, 1, 2, 3, 4, 5, 8, 0]
column = [0, 0, 0, 0, 7, 0, 0, 0, 0]

这些是第一行(或实际的任何行)和最后一列。当算法试图找到第[8]行的值时,它将始终失败,因为7被column阻止。

如果你想保持这种方式(也就是蛮力),你应该发现这种情况并重新开始。再次,这是非常低效的,你应该看看如何正确生成sudokus(我天真的方法是从一个解决的方法开始,随机交换行和列,但我知道这不是一个好方法)。