procedure solveSinglePossibilities
for each cell of the board do
if cell has no value set then
for each possible value (1..9) do
if value is single possibility according to row, column or square then
set value on cell
end if
check whether any other value is possible by checking each with row, column and square
if no other value is possible then
set value on cell
end if
end for
end if
end for
end procedure
procedure solvePossiblities
for each row, column and square of the board do
for each cell of the row, column or square do
if there are n other cells that have the same n possibilities (or fewer) then
discard these possibilities from all other cells
end if
end for
end for
end procedure
procedure solveSquarePossiblities
for each row, column and square of the board do
for each cell of the row, column or square do
if there are n other cells that have the same n possibilities (or fewer) then
for each number of these possibilities do
if all cells containing number are in same square
discard number from all other cells of square
end if
end for
end if
end for
end for
end procedure
procedure solvePossibleCells
for each cell of the board do
reset all possibilities
end for
while changes are made on cells by the calls below do
-- this sets the cells for which a single value
-- is the only possibility
call solveSinglePossibilities
-- Compute cell possibilities
for each cell of the board do
for each possible value (1..9) do
if value is possible according to row, column or square then
add value to cell possibilities
end if
end for
end for
while changes are made on cell possibilities by the calls below do
-- in each element (row, column, square) identify group
-- of possibilities and discard them from the other cells
call solvePossiblities
-- if all possibilities of a value in a row or in a column
-- are in same square, value can be discarded from other
-- cells in square.
call solveSquarePossiblities
end while
for each cell of the board do
if cell has only one possibility left then
set value as that single possibility
end if
end for
end while
end procedure
procedure solveUsingGuess
set = any one of the remaining cells with fewest possibilities
while such a cell is found do
-- Make a guess for this cell
set cell value = any one if its possibilities
-- Try to solve using that guess
call solvePossibleCells
-- If the call above made sure the board cannot be
-- solved using that guess
if board is unsolvable then
reset cell value
else if board is solved then
-- Fix guess
fix cell value -- set cell value definitely
else
call solveUsingGuess recursively
end if
end while
end procedure
procedure solve
-- solve using human-like techniques
call solvePossibleCells
-- if grid is not completed, make guesses (nishio)
call solveUsingGuess
-- with these guesses, solve the remaining cells
call solvePossibleCells
end procedure
procedure findSolutionsInternal
if current board is solved then
add a copy of current board to solutions
end if
set cell = any remaining cell without a value
for each possibility for that cell do
set cell value = that possibility
call findSolutionsInternal recursively
reset cell value
end for
end procedure
procedure findSolutions
set solutions = instantiate set of solution to be returned
-- set cell values that can be set with human-like approach
call solvePossibleCells
-- solve remaining cells with backtracking
call findSolutionsInternal with solutions and current board
return solutions
end procedure
procedure newRandomGrid
set grid = DEFAULT_GRID -- always starting with the same
perform random permutations between rows in same square groups
perform random permutations between columns in same square groups
perform random permutations between groups of rows matching squares
perform random permutations between groups of columns matching squares
-- Map every value to a new random value and swap these values
-- for every cell
remap values
return grid
end procedure
procedure performPossibleRemoves
for each cell of the grid board having a value do
set savedValue = value in that cell
reset cell value
if grid board is not solvable then-- Using backtracking solver
set cell value = savedValue
end if
end for
return number of additional cells than could be removed
end procedure
procedure removeValues
set grid = copy of original given as argument
for each cell of the grid board do
reset all values
end for
-- Add a value back for each number
for each possible value (1..9) then
pick up randomly one cell of original board containing value
assign value to corresponding cell in grid board
end for
-- Add more values until board is solvable
while grid board is not solvable do -- Using backtracking solver
-- This is key in the process. We add values back to the empty grid by choosing
-- first the cells of grid board with highest number of possibilities
set cell = pick up randomly one of most undefined cells
assign value from corresponding cell in original board
end while
-- See if there is any more values than can be removed
call performPossibleRemoves
end procedure
-- This is the one that takes a huge amount of time
procedure tryReaddingValues
set betterFound = true
while betterFound do
set betterFound = false
for each cell of the grid board without a value do
set cell value = back to former value -- former value is cell from original grid
call performPossibleRemoves
if more than two values could be removed then
set betterFound = true
break
else
reset cell value
end if
end for
end while
end procedure
procedure generateGrid
-- Create new random solved grid
set original = call newRandomGrid
-- Remove cell values as long as board remains solvable
set grid = call removeValues with original
-- see if adding back a value enables to remove more
-- Note: this is the very slow step. One can simply get rid of it
-- to get a quick but less efficient (i.e. easier boards) generator
call tryReaddingValues with grid
return grid
end procedure