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()