From 1cc386b5de18af8a0c2bb4e7cf2931200f6cf27a Mon Sep 17 00:00:00 2001 From: Henrik Blidh Date: Thu, 3 Mar 2016 16:09:13 +0100 Subject: [PATCH] Version 0.10.0 Critical fix for possible memory hog bug in the connection to the Dancing Links solver. --- README.md | 24 ++++++++++++++++++++---- dlxsudoku/sudoku.py | 18 +++++++++++++----- setup.py | 2 +- 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 6d4a950..2b27791 100644 --- a/README.md +++ b/README.md @@ -11,12 +11,11 @@ Sudoku Solver written in pure Python with no dependencies. It solves Sudokus of sizes `N x N` by pure induction as far as is possible, and then uses an optional [Dancing Links](https://en.wikipedia.org/wiki/Dancing_Links) -solver, which is a brute force methodology, when the basic -induction is not enough. +brute force solver, when the basic induction is not enough. ## Installation -Install by calling: +Install with pip: pip install dlxsudoku @@ -38,7 +37,6 @@ from dlxsudoku import Sudoku s = Sudoku.load_file('path/to/sudoku.sud') s.solve(verbose=True, allow_brute_force=True) - ``` Alternatively, if your Sudoku is stored in string variable @@ -68,6 +66,24 @@ print(s2) ``` +**DLXSudoko treats a Sudoku with multiple solutions as a faulty one +and raises a** ``dlxsudoku.exceptions.SudokuHasMultipleSolutionsError`` +**exception in such a situation.** + +### Use from terminal + +DLXSudoku also installs a console entry point. Can solve Sudokus from string or from path: + +```shell +solve-sudoku --sudoku 030467050920010006067300148301006027400850600090200400005624001203000504040030702 +``` + +or + +```shell +solve-sudoku --path "path/to/sudoku.sud" +``` + ### Sudoku formatting A Sudoku file or string should be structured in the following manner: diff --git a/dlxsudoku/sudoku.py b/dlxsudoku/sudoku.py index 890d82d..306af11 100644 --- a/dlxsudoku/sudoku.py +++ b/dlxsudoku/sudoku.py @@ -226,14 +226,22 @@ def solve(self, verbose=False, allow_brute_force=True): # Else, if singles_found is True, run another iteration to see if new singles have shown up. if not singles_found: if allow_brute_force: + solution = None try: dlxs = DancingLinksSolver(copy.deepcopy(self._matrix)) - solutions = list(dlxs.solve()) - except: + solutions = dlxs.solve() + solution = next(solutions) + more_solutions = next(solutions) + except StopIteration as e: + if solution is not None: + self._matrix = solution + else: + raise SudokuHasNoSolutionError("Dancing Links solver could not find any solution.") + except Exception as e: raise SudokuHasNoSolutionError("Brute Force method failed.") - if len(solutions) == 1: - self._matrix = solutions[0] - elif len(solutions) > 1: + else: + # We end up here if the second `next(solutions)` works, + # i.e. if multiple solutions exist. raise SudokuHasMultipleSolutionsError("This Sudoku has multiple solutions!") self.solution_steps.append("BRUTE FORCE - Dancing Links") break diff --git a/setup.py b/setup.py index 1e6c887..5edd219 100644 --- a/setup.py +++ b/setup.py @@ -30,7 +30,7 @@ setup( name='dlxsudoku', - version='0.9.3', + version='0.10.0', author='Henrik Blidh', author_email='henrik.blidh@nedomkull.com', description='Sudoku Solver in pure Python with no dependencies',