python 数独解
秒杀世界上最难的九宫数独题!
网传11级的数独题 problems\test.txt:
8 0 0 0 0 0 0 0 0
0 0 3 6 0 0 0 0 0
0 7 0 0 9 0 2 0 0
0 5 0 0 0 7 0 0 0
0 0 0 0 4 5 7 0 0
0 0 0 1 0 0 0 3 0
0 0 1 0 0 0 0 6 8
0 0 8 5 0 0 0 1 0
0 9 0 0 0 0 4 0 0
代码部分 main.py:
# -*- coding: utf-8 -*-
"""数独解法解决方案 """
from __future__ import print_function, division
import os
import copy
import time
testfile = "test.txt"
class Sudo:
def __init__(self):
self.workout = False
self.init_problem = [] # 原始题目
self.versions = [] # 记录各版本信息
self.current_version = []
self.unusable = None # 记录各单元格已用过的值
self.unusable_versions = [] # 记录各版本已用过值的信息
self.readproblem()
def readproblem(self):
problemdir = os.getcwd() + os.sep + "problems"
problemfile = open(problemdir + os.sep + testfile)
for line in problemfile.readlines():
line = line.strip()
line_list = [int(item) for item in line.split(" ")]
self.init_problem.append(line_list)
self.unusable = [[set() for i in range(0, 9)] for j in range(0, 9)]
self.current_version = self.init_problem[:]
self.versions.append(copy.deepcopy(self.current_version))
self.unusable_versions.append(copy.deepcopy(self.unusable))
def get_next_cell(self):
"""检测行,列,宫不同元素最多的非零单元格,没有则完成"""
self.print_result()
print("=====================")
this_version = self.current_version
max_items_row = None
max_items_col = None
max_items = set()
for row in range(0, 9):
for col in range(0, 9):
if not this_version[row][col]:
row_intems = set(this_version[row])
col_items = set([_row[col] for _row in this_version])
palace_items = self._palace_item(row, col, this_version)
all_items = (row_intems | col_items | palace_items) - set([0])
if len(all_items) > len(max_items):
max_items_row, max_items_col, max_items = row, col, all_items
if max_items:
userable_items = set(range(1, 10)) - max_items
self.voluation_cell(max_items_row, max_items_col, userable_items)
else:
self.workout = True
def voluation_cell(self, row, col, userable_items):
"""1 单元格赋合适的值, 记录此单元格其余可用值
2 记录该版本
3 如无合适的值,回退版本
"""
this_userable_items = userable_items - self.unusable[row][col]
if this_userable_items:
value = this_userable_items.pop()
self.current_version[row][col] = value
self.unusable[row][col].add(value)
self.unusable_versions.append(copy.deepcopy(self.unusable))
self.versions.append(copy.deepcopy(self.current_version))
# if self.versions[-1] == self.versions[-2]:
# print("the same version !!!")
# print(row, col, value)
# for item in self.versions:
# print("-------------------")
# self.print_result(item)
# print("current_version-------------------")
# self.print_result()
# exit(1)
else:
self.back_last_version()
def back_last_version(self):
s = self.versions.pop()
if not self.versions:
print("No solution")
exit(1)
self.current_version = copy.deepcopy(self.versions[-1])
u = self.unusable_versions.pop()
self.unusable = copy.deepcopy(u)
# if s == self.current_version:
# print("The version is not unicity!")
# self.print_result(s)
# print("#############")
# self.print_result()
# exit(1)
def _palace_item(self, row, col, sudo):
palace_row = int((row / 3))
palace_col = int((col / 3))
m = range(palace_row * 3, (palace_row + 1) * 3)
n = range(palace_col * 3, (palace_col + 1) * 3)
l = [sudo[i][j] for i in m for j in n]
return set(l)
def print_result(self, version=None):
if version:
this_version = version
else:
this_version = self.current_version
for item in this_version:
print(str(item).replace("[", "").replace("]", "").replace(",", ""))
def run(self):
while not self.workout:
self.get_next_cell()
print("workout!! the result is ......")
self.print_result()
if __name__ == "__main__":
Sudo().run()