目标是在Python中创建一个9x9 Sudoku矩阵。
所以我到目前为止。但我似乎无法让程序让内部特遣队正确。
def sudoku(size):
import random as rn
mydict = {}
n = 0
while len(mydict) < 9:
n += 1
x = range(1, size+1)
testlist = rn.sample(x, len(x))
isgood = True
for dictid,savedlist in mydict.items():
if isgood == False:
break
for v in savedlist:
if testlist[savedlist.index(v)] == v:
isgood = False
break
if isgood == True:
#print 'success', testlist
mydict[len(mydict)] = testlist
return mydict, n
return_dict, total_tries = sudoku(9)
for n,v in return_dict.items():
print n,v
print 'in',total_tries,'tries'
答案 0 :(得分:1)
您可以生成一个随机数独板,在其中填写所有数字,然后删除其中的一些数字以创建拼图。这将向您保证拼图有解决方案。确保它只有一个解决方案更具挑战性,并且更具挑战性,因此您要删除更多的数字(提示:9x9数独必须至少保留17个数字)
下面的算法几乎会在N <1000时立即生成NxN个随机数独板。
from random import sample
base = 3 # Will generate any size of random sudoku board in O(n^2) time
side = base*base
nums = sample(range(1,side+1),side) # random numbers
board = [[nums[(base*(r%base)+r//base+c)%side] for c in range(side) ] for r in range(side)]
rowGr = sample(range(base),base) # random rows/horizontal blocks
rows = [ r for g in rowGr for r in sample(range(g*base,(g+1)*base),base) ]
colGr = sample(range(base),base) # random column/vertical blocks
cols = [ c for g in colGr for c in sample(range(g*base,(g+1)*base),base) ]
board = [[board[r][c] for c in cols] for r in rows]
for line in board: print(line)
[8, 5, 7, 9, 3, 4, 2, 6, 1]
[9, 4, 3, 6, 1, 2, 5, 8, 7]
[6, 2, 1, 8, 7, 5, 4, 9, 3]
[2, 1, 9, 5, 6, 7, 3, 4, 8]
[5, 7, 6, 4, 8, 3, 1, 2, 9]
[4, 3, 8, 2, 9, 1, 7, 5, 6]
[1, 9, 4, 7, 2, 6, 8, 3, 5]
[3, 8, 5, 1, 4, 9, 6, 7, 2]
[7, 6, 2, 3, 5, 8, 9, 1, 4]
然后您可以从有效的数独板中删除一些数字以创建拼图:
for _ in range(side*side//2): # remove more to make it more difficult
r,c = sample(range(side),2)
board[r][c] = 0
for line in board: print("["+" ".join(f"{n or '.'}" for n in line)+"]")
[8 . 7 9 . . 2 6 1]
[9 4 . 6 . . 5 8 7]
[. 2 1 8 7 . 4 . 3]
[2 . . 5 . . . . 8]
[5 . . 4 8 . 1 2 .]
[. 3 8 2 . 1 7 5 .]
[1 9 . . 2 6 8 3 .]
[. 8 . 1 4 9 . 7 2]
[. . 2 3 5 . . . 4]
答案 1 :(得分:0)
这应该有用。
def sudoku(size):
import time
start_time=time.time()
import sys
import random as rn
mydict = {}
n = 0
print '--started calculating--'
while len(mydict) < 9:
n += 1
x = range(1, size+1)
testlist = rn.sample(x, len(x))
isgood = True
for dictid,savedlist in mydict.items():
if isgood == False:
break
for v in savedlist:
if testlist[savedlist.index(v)] == v:
isgood = False
break
if isgood == True:
isgoodafterduplicatecheck = True
mod = len(mydict) % 3
dsavedlists = {}
dtestlists = {}
dcombindedlists = {}
for a in range(1,mod + 1):
savedlist = mydict[len(mydict) - a]
for v1 in savedlist:
modsavedlists = (savedlist.index(v1) / 3) % 3
dsavedlists[len(dsavedlists)] = [modsavedlists,v1]
for t1 in testlist:
modtestlists = (testlist.index(t1) / 3) % 3
dtestlists[len(dtestlists)] = [modtestlists,t1]
for k,v2 in dsavedlists.items():
dcombindedlists[len(dcombindedlists)] = v2
dcombindedlists[len(dcombindedlists)] = dtestlists[k]
vsave = 0
lst1 = []
for k, vx in dcombindedlists.items():
vnew = vx[0]
if not vnew == vsave:
lst1 = []
lst1.append(vx[1])
else:
if vx[1] in lst1:
isgoodafterduplicatecheck = False
break
else:
lst1.append(vx[1])
vsave = vnew
if isgoodafterduplicatecheck == True:
mydict[len(mydict)] = testlist
print 'success found', len(mydict), 'row'
print '--finished calculating--'
total_time = time.time()-start_time
return mydict, n, total_time
return_dict, total_tries, amt_of_time = sudoku(9)
print ''
print '--printing output--'
for n,v in return_dict.items():
print n,v
print 'process took',total_tries,'tries in', round(amt_of_time,2), 'secs'
print '-------------------'
答案 2 :(得分:0)
如果您的目标是创建 9 x 9 Sudoku,那么为什么不开发一个更简单的程序呢? 这不必是恒定时间。 您可以更改元组的长度 对于任何 n!的n ^ 2 x n ^ 2 的倍数。然后手动删除 创造谜题的要素。
tup = input()[1:-1].split(',')
x = input('Enter mapping to generate valid Sudoku eg. 3 for 9 x 9')
e = input('Enter 9 for 9 x 9 ...12 for 12 x 12')
f = input('Enter 3 if its a 9 x 9 and corresponding for n^2 x n^2')
x = int(x)
e = int(e)
f = int(f)
squares = []
for index in range(len(tup)):
tup.append(tup.pop(0))
squares.append(tup.copy())
#Everything below here is just printing
for s in range(x):
for d in range(0,e,f):
for si in range(s,e,f):
for li in range(d,d+f):
print(squares[si][li], end = '')
print('')
#Remember that if you want
#to create n! of n^2 x n^2
#you need to edit the below
#for a valid grid
#for example
#a 9 x 9
#would be a 3 x 3
#and so on.
侧面注:如果要创建12 x 12或任何更大的Sudoku。您需要编辑元组,以便值可读。 例如。 ['[01]','[02]',....]
此外,我还有一个好友,他帮助我将算法转换为我的业余Sudoku项目的python代码。感谢那个Reddit用户。
答案 3 :(得分:-2)
首先,随机创建一个完整的数独解决方案。这部分需要有一个数独求解器。
从数独解决方案中,不断删除随机位置的数字。对于每次删除,检查数独是否仍然有效。也就是说,数独有一个独特的解决方案。这部分需要找出是否有多个解决方案。这是数独求解器的另一个版本。
如果没有,我们将号码放回并尝试另一个位置。该过程一直持续到所有位置都尝试过为止。
import random
import numpy as np
def PossibleValueAtPosition(pz:[], row:int, col:int):
r=row//3*3
c=col//3*3
return {1,2,3,4,5,6,7,8,9}.difference(set(pz[r:r+3,c:c+3].flat)).difference(set(pz[row,:])).difference(set(pz[:,col]))
def Solution_Count(pz:[], n:int, Nof_solution:int):
if Nof_solution>1:
return Nof_solution
if n>=81:
Nof_solution+=1
return Nof_solution
(row,col) = divmod(n,9)
if pz[row][col]>0:
Nof_solution = Solution_Count(pz, n+1, Nof_solution)
else:
l = PossibleValueAtPosition(pz, row,col)
for v in l:
pz[row][col] = v
Nof_solution = Solution_Count(pz, n+1, Nof_solution)
pz[row][col] = 0
return Nof_solution
def SudokuSolver(pz:[], n:int):
if n==81:
return True
(row,col) = divmod(n,9)
if pz[row][col]>0:
if SudokuSolver(pz, n+1):
return True
else:
l = list(PossibleValueAtPosition(pz, row,col))
random.shuffle(l)
for v in l:
pz[row][col] = v
if SudokuSolver(pz, n+1):
return True
pz[row][col] = 0
return False
def DigHoles(pz:[], randomlist:[], n:int, nof_holes:int):
if n>=81 or nof_holes>=64:
return
(row,col) = divmod(randomlist[n],9)
if pz[row][col]>0:
pz_check=pz.copy()
pz_check[row][col]=0
Nof_solution = Solution_Count(pz_check, 0, 0)
if Nof_solution==1:
pz[row][col]=0
nof_holes+=1
print(pz)
print("{} zeros".format(nof_holes))
print()
DigHoles(pz, randomlist, n+1, nof_holes)
def main():
puzzle = np.zeros((9,9), dtype=int)
SudokuSolver(puzzle, 0)
print(puzzle, "--------- Answer\n")
randomlist = list(range(81))
random.shuffle(randomlist)
DigHoles(puzzle, randomlist, 0, 0)
if __name__ == "__main__":
main()