patternpythonMinor
Sudoku Puzzle Solver
Viewed 0 times
solversudokupuzzle
Problem
I have written a program to solve Sudoku puzzles as a (fun?) way to learn Python. It solves puzzles as a human would, using reasoning algorithms rather than brute force/backtracking, as I thought it would a more interesting challenge that way.
I really looking for any feedback on how to reduce indentation, lines of code, or increase efficiency. I'm sure the functions that I've repeated for columns/rows/subgrids can be merged into one, but I just can't think of an elegant way. Any general feedback would be more than welcome too, please lay into the code as much as possible. I'm a 2nd year computing (CS but lite) student if that makes any difference but probably not.
I appreciate this involves domain specific knowledge i.e. how to solve Sudoku puzzles. I created all the algorithms using only the following resource and all of the techniques contained in the program are described here for anyone interested.
```
import itertools
# TERMINOLOGY
# grid: The main 9x9 grid of the puzzle.
# sub-grid: A 3x3 sub-grid within the main grid.
# square: A single square within the grid.
# row: A whole row of squares within the main grid.
# column: A whole column of squares within the main grid.
# sub-row: A row of three squares in a sub-grid.
# sub-column: A column of three squares in a sub-grid.
# candidate: A possible solution for a square.
# solved: A square is solved when the correct value is filled.
#
# For in-depth descriptions of the various sudoku solving techniques
# used in this program, visit:
# http://www.paulspages.co.uk/sudoku/howtosolve/index.htm
# This is the sole resource used to generate the techniques
# found in this program.
# Holds puzzle itself as 2d list. Blank squares represented as 0.
# Individual square access: main_grid[x][y]
main_grid = [[] for x in range(0, 9)]
# Holds all possible candidates for each square as a 2d list of sets.
# Individual square set access: candidates_grid[x][y]
candidates_grid =
I really looking for any feedback on how to reduce indentation, lines of code, or increase efficiency. I'm sure the functions that I've repeated for columns/rows/subgrids can be merged into one, but I just can't think of an elegant way. Any general feedback would be more than welcome too, please lay into the code as much as possible. I'm a 2nd year computing (CS but lite) student if that makes any difference but probably not.
I appreciate this involves domain specific knowledge i.e. how to solve Sudoku puzzles. I created all the algorithms using only the following resource and all of the techniques contained in the program are described here for anyone interested.
```
import itertools
# TERMINOLOGY
# grid: The main 9x9 grid of the puzzle.
# sub-grid: A 3x3 sub-grid within the main grid.
# square: A single square within the grid.
# row: A whole row of squares within the main grid.
# column: A whole column of squares within the main grid.
# sub-row: A row of three squares in a sub-grid.
# sub-column: A column of three squares in a sub-grid.
# candidate: A possible solution for a square.
# solved: A square is solved when the correct value is filled.
#
# For in-depth descriptions of the various sudoku solving techniques
# used in this program, visit:
# http://www.paulspages.co.uk/sudoku/howtosolve/index.htm
# This is the sole resource used to generate the techniques
# found in this program.
# Holds puzzle itself as 2d list. Blank squares represented as 0.
# Individual square access: main_grid[x][y]
main_grid = [[] for x in range(0, 9)]
# Holds all possible candidates for each square as a 2d list of sets.
# Individual square set access: candidates_grid[x][y]
candidates_grid =
Solution
Working with file handles
Don't do this:
Use
In your version you forget to close the file handle.
That's a bad practice.
When using
Use booleans
Instead of returning 0 for failure and 1 for success:
Use booleans:
Usability
It would be nice if the puzzle file was a command line argument,
not the hardcoded path
Documentation
It's nice that you included explanation about the terminology.
But it would be better to use proper doc strings.
Simplifications
You can replace this:
With a set literal:
You can write
Instead of
Don't do this:
puzzle = open('../puzzles/extreme2.txt', 'r')Use
with instead:with open('../puzzles/extreme2.txt') as puzzle:
# ...In your version you forget to close the file handle.
That's a bad practice.
When using
with, the file handle is automatically closed.Use booleans
Instead of returning 0 for failure and 1 for success:
def is_solved():
for y in range(0, 9):
if len(row_set[y]) != 9:
return 0
return 1Use booleans:
def is_solved():
for y in range(0, 9):
if len(row_set[y]) != 9:
return False
return TrueUsability
It would be nice if the puzzle file was a command line argument,
not the hardcoded path
../puzzles/extreme2.txt.Documentation
It's nice that you included explanation about the terminology.
But it would be better to use proper doc strings.
Simplifications
You can replace this:
full_set = set({1, 2, 3, 4, 5, 6, 7, 8, 9})With a set literal:
full_set = {1, 2, 3, 4, 5, 6, 7, 8, 9}You can write
range(9) instead of range(0, 9)Instead of
int(x / 3), it's better to use x // 3Code Snippets
puzzle = open('../puzzles/extreme2.txt', 'r')with open('../puzzles/extreme2.txt') as puzzle:
# ...def is_solved():
for y in range(0, 9):
if len(row_set[y]) != 9:
return 0
return 1def is_solved():
for y in range(0, 9):
if len(row_set[y]) != 9:
return False
return Truefull_set = set({1, 2, 3, 4, 5, 6, 7, 8, 9})Context
StackExchange Code Review Q#96792, answer score: 7
Revisions (0)
No revisions yet.