深度搜索+命令模式 解数独,深度命令模式解数,def flatten(
def flatten(nested_list): for value in nested_list: if isinstance(value, list): for nested_value in flatten(value): yield nested_value else: yield valuedef some(nested_list, fn): for value in flatten(nested_list): if fn(value): return value return Noneclass Cell(set): def __init__(self, y, x): self.marked = False self.y = y self.x = x self.update(range(1, 10)) def is_explicit(self): return len(self) == 1 def mark(self, value): self.marked = True self.clear() self.add(value) def set(self, values): self.marked = False self.clear() self.update(values) def value(self): return next(iter(self)) def __str__(self): size = len(self) if size == 0: return 'X' elif size == 1: return str(self.value()) else: return '?'class Table: def __init__(self): self.values = [[Cell(y, x) for x in xrange(9)] for y in xrange(9)] def is_valid(self): return all(flatten(self.values)) def is_finished(self): return all([e.is_explicit() for e in flatten(self.values)]) def first_implicit(self): return some(self.values, lambda e: not e.is_explicit()) def first_explicit(self): return some(self.values, lambda e: not e.marked and e.is_explicit()) def get_neighbors(self, y, x): neighbors = [] # horizontal neighbors.extend([self.values[y][c] for c in xrange(9) if c != x and not self.values[y][c].marked]) # vertical neighbors.extend([self.values[r][x] for r in xrange(9) if r != y and not self.values[r][x].marked]) # box start_x = x / 3 * 3 start_y = y / 3 * 3 for r in range(start_y, start_y + 3): for c in range(start_x, start_x + 3): if r != y and c != x and not self.values[r][c].marked: neighbors.append(self.values[r][c]) return neighbors def __str__(self): return '\n'.join([' '.join(str(c) for c in r) for r in self.values])class Command: def __init__(self, table, y, x, value): self.table = table self.y = y self.x = x self.value = value self.cell = table.values[y][x].copy() self.queue = [] self.executed = False def redo(self): if self.executed: return else: self.executed = True self.queue = [] for cell in self.table.get_neighbors(self.y, self.x): if self.value in cell: cell.remove(self.value) self.queue.append(cell) self.table.values[self.y][self.x].mark(self.value) def undo(self): if self.executed: self.executed = False else: return for cell in self.queue: cell.add(self.value) self.table.values[self.y][self.x].set(self.cell)class Sudoku: def __init__(self): self.table = Table() self.queue = [] def push(self, y, x, value): cmd = Command(self.table, y, x, value) cmd.redo() self.queue.append(cmd) def pop(self): cmd = self.queue.pop() cmd.undo() def load(self, matrix): for y, line in zip(range(9), matrix.strip().split('\n')): for x, value in zip(range(9), line.strip().split(' ')): if value != '?': self.push(y, x, int(value)) self.derive() def derive(self): count = 0 while True: cell = self.table.first_explicit() if cell: self.push(cell.y, cell.x, cell.value()) count += 1 else: return count def revert(self, deep): for i in xrange(-1, deep): self.pop() def bfs(self): cell = self.table.first_implicit() for value in cell.copy(): self.push(cell.y, cell.x, value) deep = self.derive() if self.table.is_finished(): return True elif not self.table.is_valid(): self.revert(deep) else: result = self.bfs() if result: return True else: self.revert(deep) return False def __str__(self): return str(self.table)puzzle = '''? ? ? ? ? 7 ? 8 25 ? 7 ? ? ? 4 ? ?? ? ? 2 5 ? ? ? ?8 ? 9 1 7 ? ? ? ?? 7 ? 5 ? 3 6 ? 8? 5 3 ? ? ? ? 9 12 ? ? ? ? ? 3 ? 6? ? ? 3 ? 2 ? ? ?? 8 5 ? 6 ? ? ? ?'''sudoku = Sudoku()sudoku.load(puzzle)sudoku.bfs()print sudoku
评论关闭