Package: basicsudoku
A simple, basic Sudoku class in Python. Suitable for programming tutorials or experimentation.Thebasicsudokumodule provides just the data structure for a 9x9 sudoku board, along with a basic solver. This module can be usedInstallationpip install basicsudokuGetting Started>>> import basicsudoku
>>> board = basicsudoku.SudokuBoard() # Get a blank board.
>>> print(board)
>>> print(board)
. . . | . . . | . . .
. . . | . . . | . . .
. . . | . . . | . . .
------+-------+------
. . . | . . . | . . .
. . . | . . . | . . .
. . . | . . . | . . .
------+-------+------
. . . | . . . | . . .
. . . | . . . | . . .
. . . | . . . | . . .
>>> board[0, 0] = 1
>>> board[1, 0] = '2'
>>> board[8, 8] = 3
>>> print(board)
1 2 . | . . . | . . .
. . . | . . . | . . .
. . . | . . . | . . .
------+-------+------
. . . | . . . | . . .
. . . | . . . | . . .
. . . | . . . | . . .
------+-------+------
. . . | . . . | . . .
. . . | . . . | . . .
. . . | . . . | . . 3
>>> board.symbols
'12..............................................................................3'
>>> board.symbols = '2...8.3...6..7..84.3.5..2.9...1.54.8.........4.27.6...3.1..7.4.72..4..6...4.1...3'
>>> print(board)
2 . . | . 8 . | 3 . .
. 6 . | . 7 . | . 8 4
. 3 . | 5 . . | 2 . 9
------+-------+------
. . . | 1 . 5 | 4 . 8
. . . | . . . | . . .
4 . 2 | 7 . 6 | . . .
------+-------+------
3 . 1 | . . 7 | . 4 .
7 2 . | . 4 . | . 6 .
. . 4 | . 1 . | . . 3>>> solver = basicsudoku.BasicSolver(board)
>>> print(board)
2 4 5 | 9 8 1 | 3 7 6
1 6 9 | 2 7 3 | 5 8 4
8 3 7 | 5 6 4 | 2 1 9
------+-------+------
9 7 6 | 1 2 5 | 4 3 8
5 1 3 | 4 9 8 | 6 2 7
4 8 2 | 7 3 6 | 9 5 1
------+-------+------
3 9 1 | 6 5 7 | 8 4 2
7 2 8 | 3 4 9 | 1 6 5
6 5 4 | 8 1 2 | 7 9 3>>> board2 = basicsudoku.SudokuBoard(symbols='2...8.3...6..7..84.3.5..2.9...1.54.8.........4.27.6...3.1..7.4.72..4..6...4.1...3')
>>> print(board2)
2 . . | . 8 . | 3 . .
. 6 . | . 7 . | . 8 4
. 3 . | 5 . . | 2 . 9
------+-------+------
. . . | 1 . 5 | 4 . 8
. . . | . . . | . . .
4 . 2 | 7 . 6 | . . .
------+-------+------
3 . 1 | . . 7 | . 4 .
7 2 . | . 4 . | . 6 .
. . 4 | . 1 . | . . 3Definitionsboard- The full 9 x9 board, consisting of 81 spaces.space- One of the 81 places on the board where a symbol can be placed.symbol- A number from 1 to 9 that is placed on the board. A space can also be empty.length- The length of the board (either height or width), which is 9 in standard Sudoku.unit- A collection of 9 symbols from a row, column, or box.box- One of the nine 3x3 subgrids on the board.column- Nine vertical spaces on the board.row- Nine horizontal spaces on the board.given- A symbol that is on the board at the start of a puzzle.peer- The spaces in the same row, column, or box as a specified space.APIThebasicsudokumodule is meant to be easy to learn. All methods have descriptive docstrings and the code is well-commented.Create a Sudoku BoardCreating an empty Sudoku board:>>> board = basicsudoku.SudokuBoard()Prepopulate a board with symbols:>>> board = basicsudoku.SudokuBoard(symbols='2...8.3...6..7..84.3.5..2.9...1.54.8.........4.27.6...3.1..7.4.72..4..6...4.1...3')Disable strict mode (strict mode causes an exception to be raised if you place a symbol on the board that makes it invalid.)>>> board = basicsudoku.SudokuBoard(strict=False)Or:>>> board = basicsudoku.SudokuBoard()
>>> board.strict = FalseSet and Get SymbolsYou can assign integers or strings from 1 to 9 to an xy tuple index:>>> board = basicsudoku.SudokuBoard()
>>> board[0, 0] = '1'
>>> board[0, 0]
'1'
>>> board[1, 0] = 2
>>> board[1, 0]
'2'You can use thesymbolsattribute to get or set all of the symbols at once:>>> board = basicsudoku.SudokuBoard()
>>> board.symbols = '4.....8.5.3..........7......2.....6.....8.4......1.......6.3.7.5..2.....1.4......'
>>> print(board)
4 . . | . . . | 8 . 5
. 3 . | . . . | . . .
. . . | 7 . . | . . .
------+-------+------
. 2 . | . . . | . 6 .
. . . | . 8 . | 4 . .
. . . | . 1 . | . . .
------+-------+------
. . . | 6 . 3 | . 7 .
5 . . | 2 . . | . . .
1 . 4 | . . . | . . .You can also get a unit (9 symbols) from a row, column, or box with these methods:>>> board = basicsudoku.SudokuBoard(symbols='4.....8.5.3..........7......2.....6.....8.4......1.......6.3.7.5..2.....1.4......')
>>> print(board)
4 . . | . . . | 8 . 5
. 3 . | . . . | . . .
. . . | 7 . . | . . .
------+-------+------
. 2 . | . . . | . 6 .
. . . | . 8 . | 4 . .
. . . | . 1 . | . . .
------+-------+------
. . . | 6 . 3 | . 7 .
5 . . | 2 . . | . . .
1 . 4 | . . . | . . .
>>> board.get_row(0)
['4', '.', '.', '.', '.', '.', '8', '.', '5']
>>> board.get_row(1)
['.', '3', '.', '.', '.', '.', '.', '.', '.']
>>> board.get_column(0)
['4', '.', '.', '.', '.', '.', '.', '5', '1']
>>> board.get_box(0, 0)
['4', '.', '.', '.', '3', '.', '.', '.', '.']
>>> board.get_box(1, 0)
['.', '.', '.', '.', '.', '.', '7', '.', '.']Validation ChecksBy default,SudokuBoardobjects are instrict mode, meaning any symbols added to the board that make the boardinvalid(this is, have duplicate symbols in the same row, column, or box) will cause aSudokuBoardExceptionto be raised. You can set the keyword argumentstrict=Falsein the constructor method call to disable this. There are also several validation checking methods:is_valid_symbol(self, symbol)- Returns True if symbol is a str between 1 and 9, or is EMPTY_SPACE.is_complete_unit(self, unit)- Returns True if unit is a str of all 9 symbols with no repeats.is_valid_unit(self, unit)- Returns True if unit is a str of 9 symbols, which can include EMPTY_SPACE but doesn’t have repeated symbols.is_valid_board(self)- Returns True if the board is in a valid state (even if incomplete), otherwise return False if the board has repeated symbols set to any of the rows, columns, or boxes.is_full(self)- Returns True if there are no empty spaces on the board.is_solved(self)- Returns True if the board is currently solved.IteratorYou can iterate over the symbols in the board, starting from the top left and going right, then down. For example:>>> board = basicsudoku.SudokuBoard(symbols='4.....8.5.3..........7......2.....6.....8.4......1.......6.3.7.5..2.....1.4......')
>>> for symbol in board:
...     print(symbol, end=' ')
...
4 . . . . . 8 . 5 . 3 . . . . . . . . . . 7 . . . . . . 2 . . . . . 6 . . . . . 8 . 4 . . . . . . 1 . . . . . . . 6 . 3 . 7 . 5 . . 2 . . . . . 1 . 4 . . . . . .Solving Sudoku PuzzlesTheBasicSolverclass is passed aSudokuBoardobject and immediately solves it.>>> board = SudokuBoard(symbols='4.....8.5.3..........7......2.....6.....8.4......1.......6.3.7.5..2.....1.4......')
>>> print(board)
4 . . | . . . | 8 . 5
. 3 . | . . . | . . .
. . . | 7 . . | . . .
------+-------+------
. 2 . | . . . | . 6 .
. . . | . 8 . | 4 . .
. . . | . 1 . | . . .
------+-------+------
. . . | 6 . 3 | . 7 .
5 . . | 2 . . | . . .
1 . 4 | . . . | . . .
>>> solver = BasicSolver(board)
>>> print(board)
4 1 7 | 3 6 9 | 8 2 5
6 3 2 | 1 5 8 | 9 4 7
9 5 8 | 7 2 4 | 3 1 6
------+-------+------
8 2 5 | 4 3 7 | 1 6 9
7 9 1 | 5 8 6 | 4 3 2
3 4 6 | 9 1 2 | 7 5 8
------+-------+------
2 8 9 | 6 4 3 | 5 7 1
5 7 3 | 2 9 1 | 6 8 4
1 6 4 | 8 7 5 | 2 9 3Included Sudoku PuzzlesThe puzzles provided by Peter Norvig’s sudoku page are included. Thebasicsudoku.easy50list contains 50 easy puzzles, thebasicsudoku.top95list contains 95 puzzles, andbasicsudoku.hardestcontains 11 very difficult puzzles. Pass the 81-character strings in these lists to thesymbolskeyword argument in theSudokuBoardconstructor to load them onto the board.Unit TestsThe module has pytest unit tests in thetests/test_basic.pyfile, as well as doctests in the main module’s docstrings. The coverage.py tool can be run over the module as well, and the latest report is in thehtmlcov/index.htmlfile.RoadmapIn the future I plan on adding a puzzle generator, with variable difficulty setting. I’d also like the solver to detect if there are multiple solutions to a board.basicsudokuis written for readability, not performance. There are many places where the performance could be improved, especially in the solver. There are no plans for improving the performance. This module was made as a learning tool, not as an efficient sudoku solver (of which there are already many).