HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Sudoku Puzzle Solver

Submitted by: @import:stackexchange-codereview··
0
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 =

Solution

Working with file handles

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 1


Use booleans:

def is_solved():
    for y in range(0, 9):
        if len(row_set[y]) != 9:
            return False
    return True


Usability

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 // 3

Code 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 1
def is_solved():
    for y in range(0, 9):
        if len(row_set[y]) != 9:
            return False
    return True
full_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.