def __init__(self): self._dlx_solver = DLXSolver()
class SudokuSolver(object): digits = set(map(str, range(1, 10))) GRID_OFFSET = 0 ROW_OFFSET = 81 COLUMN_OFFSET = 162 BOX_OFFSET = 243 def __init__(self): self._dlx_solver = DLXSolver() def solve(self, puzzle): """Solve the given Soduku puzzle :Parameters: puzzle: str The puzzle can either be single-lined or multi-lined. Use 1-9 to represent the filled numbers, any other printable characters will be considered as blanks. :Return: solution: [(row, col, val), ... ] The solution is a list of a 3-elements tuple. both row and col are 0-8, val is 1-9 """ dlx_matrix = self._construct(puzzle) solution = self._dlx_solver.solve(dlx_matrix, 324) return [(row, col, val + 1) for row, col, val in solution] def _construct(self, puzzle): """Helper function for constructing a matrix used by DLXSolver from the given puzzle """ linear_puzzle = "".join(puzzle.split()) if len(linear_puzzle) != 81: print "Invalid puzzle." return dlx_matrix = {} for i, c in enumerate(linear_puzzle): row, col = divmod(i, 9) if c in self.digits: val = int(c) - 1 dlx_matrix[(row, col, val)] = self._get_ones(row, col, val) else: for val in xrange(9): dlx_matrix[(row, col, val)] = self._get_ones(row, col, val) return dlx_matrix def _get_ones(self, row, col, val): """Helper function to generate a 4-elements list from the given row, col and val. The value of each element indicates there's a node in the corresponding column in the DLX matrix. """ ones = [ 9 * row + col + self.GRID_OFFSET, 9 * row + val + self.ROW_OFFSET, 9 * col + val + self.COLUMN_OFFSET, (row // 3 * 3 + col // 3) * 9 + val + self.BOX_OFFSET, ] return ones
class SudokuSolver(object): digits = set(map(str, range(1, 10))) GRID_OFFSET = 0 ROW_OFFSET = 81 COLUMN_OFFSET = 162 BOX_OFFSET = 243 def __init__(self): self._dlx_solver = DLXSolver() def solve(self, puzzle): """Solve the given Soduku puzzle :Parameters: puzzle: str The puzzle can either be single-lined or multi-lined. Use 1-9 to represent the filled numbers, any other printable characters will be considered as blanks. :Return: solution: [(row, col, val), ... ] The solution is a list of a 3-elements tuple. both row and col are 0-8, val is 1-9 """ dlx_matrix = self._construct(puzzle) solution = self._dlx_solver.solve(dlx_matrix, 324) return [(row, col, val + 1) for row, col, val in solution] def _construct(self, puzzle): """Helper function for constructing a matrix used by DLXSolver from the given puzzle """ linear_puzzle = ''.join(puzzle.split()) if len(linear_puzzle) != 81: print 'Invalid puzzle.' return dlx_matrix = {} for i, c in enumerate(linear_puzzle): row, col = divmod(i, 9) if c in self.digits: val = int(c) - 1 dlx_matrix[(row, col, val)] = self._get_ones(row, col, val) else: for val in xrange(9): dlx_matrix[(row, col, val)] = self._get_ones(row, col, val) return dlx_matrix def _get_ones(self, row, col, val): """Helper function to generate a 4-elements list from the given row, col and val. The value of each element indicates there's a node in the corresponding column in the DLX matrix. """ ones = [9 * row + col + self.GRID_OFFSET, 9 * row + val + self.ROW_OFFSET, 9 * col + val + self.COLUMN_OFFSET , (row // 3 * 3 + col // 3) * 9 + val + self.BOX_OFFSET] return ones