2017-08-16 22:54:45 +08:00

202 lines
4.1 KiB
Python

from copy import deepcopy
n = 3
maxx = n ** 2
allc = list(xrange(1, maxx + 1))
for i in xrange(len(allc)):
allc[i] = str(allc[i])
area = []
for x in xrange(maxx):
area.append([(x, i) for i in xrange(maxx)])
for y in xrange(maxx):
area.append([(i, y) for i in xrange(maxx)])
for i in xrange(n):
for j in xrange(n):
area.append([(x, y) for x in xrange(n * i, n * i + n) for y in xrange(n * j, n * j + n)])
def psh(x):
return [(x, i) for i in xrange(maxx)]
def psv(y):
return [(i, y) for i in xrange(maxx)]
def psb(x, y):
x0 = x // n * n
y0 = y // n * n
return [(i, j) for i in xrange(x0, x0 + n) for j in xrange(y0, y0 + n)]
def unit(x, y, flag = 4):
out = set([])
if flag == 1 or flag > 3:
for i in xrange(maxx):
out.add((x, i))
if flag == 2 or flag > 3:
for i in xrange(maxx):
out.add((i, y))
if flag == 3 or flag > 3:
x0 = x // n * n
y0 = y // n * n
for i in xrange(x0, x0 + n):
for j in xrange(y0, y0 + n):
out.add((i, j))
return list(out)
def psudo(matrix):
for i in xrange(maxx):
for j in xrange(maxx):
if j % n == 0:
#print(' ', end='')
print '',
print matrix[i][j] + ' ',# end='')
print('')
if i % n == n - 1:
print('')
def get(point, matrix):
out = set([])
for i in point:
out.add(matrix[i[0]][i[1]])
out.discard('0')
return out
def init(matrix):
out = {}
haveh = [get(psh(i), matrix) for i in xrange(maxx)]
havev = [get(psv(i), matrix) for i in xrange(maxx)]
haveb = [[get(psb(i * n, j * n), matrix) for j in xrange(n)] for i in xrange(n)]
for i in xrange(maxx):
for j in xrange(maxx):
if matrix[i][j] == '0':
tmp = set(allc)
tmp -= haveh[i]
tmp -= havev[j]
tmp -= haveb[i // n][j // n]
out.update({(i, j): tmp})
return out
def rmkey(k, dic, matrix, value = ''):
tmp = list(dic[k])[0]
if len(value) == 1:
tmp = value
dic.pop(k)
matrix[k[0]][k[1]] = tmp
for p in unit(k[0], k[1]):
if p in dic.keys():
dic[p].discard(tmp)
def one(dic, matrix):
while 1:
for k in dic.keys():
if len(dic[k]) == 1:
rmkey(k, dic, matrix)
break
else:
return
def getd(dic):
for i in sorted(dic):
print i, dic[i]
def diff(dic, matrix):
if len(dic.keys()) < 2:
return
for parea in area:
pnow = parea[:]
tt = []
have = set([])
for pp in parea:
if pp in dic.keys():
tt.extend(list(dic[pp]))
have |= dic[pp]
else:
pnow.remove(pp)
for i in have:
if tt.count(i) == 1:
for thek in pnow:
try:
if i in dic[thek]:
rmkey(thek, dic, matrix, i)
except:
pass
#print thek
#getd(dic)
#psudo(matrix)
#continue
def esay(dic, matrix, trytime = 20):
limit = 0
#out = ''.join(matrix[0][:n])
while limit < trytime: #'0' in out and
one(dic, matrix)
diff(dic, matrix)
#out = ''.join(matrix[0][:n])
limit += 1
#psudo(matrix)
if limit < trytime:
return True
else:
for test in dic.values():
if len(test) < 1:
return False
return True
def solve(matrix, trytime = 10):
dicc = init(matrix)
out = ''.join(matrix[0][:n])
limit = 0
while '0' in out:
limit += 1
if limit > trytime:
for p in dicc.keys():
if len(dicc[p]) == 2:
matrix_ = deepcopy(matrix)
dicc_ = deepcopy(dicc)
rmkey(p, dicc_, matrix_, list(dicc[p])[0])
if esay(dicc_, matrix_):
dicc = dicc_
matrix = matrix_
else:
rmkey(p, dicc, matrix, list(dicc[p])[1])
limit = 0
break
else:
break
if esay(dicc, matrix):
out = ''.join(matrix[0][:n])
limit += 1
return int(out)
def main():
ff = open('sudoku.txt', 'r')
nums = 0
total = 0
while nums < 50:
ff.readline()
aa = []
nums += 1
for i in xrange(maxx):
aa.append('.'.join(ff.readline().strip()).split('.'))
tmp = solve(aa)
print tmp
total += tmp
print '***', total
main()