I had always been interested in solving sudoku puzzles, partly because there are too many combinations that make each Sudoku unique. Since my work involves writing and using programming in different scenarios, I thought why not try using my skills on Sudoku. So there I was on a London Underground train to Barbican - looking at a Sudoku puzzle at the back of a morning newspaper, wondering how I can write an algorithm to solve it. I figured out a few simple tricks that I have always used in algorithm design. Here I explain what thoughts I had while designing my very own Sudoku solver and how I transformed those ideas into a working prototype.
and the solution of the above sudoku puzzle:
sudokuUnsolved =
5 3 0 0 7 0 0 0 0
6 0 0 1 9 5 0 0 0
0 9 8 0 0 0 0 6 0
8 0 0 0 6 0 0 0 3
4 0 0 8 5 3 0 0 1
7 0 0 0 2 0 0 0 6
0 6 0 0 3 7 2 8 4
0 0 0 4 1 9 0 3 5
0 0 0 0 8 0 0 7 9
sudokuUnsolved =
5 3 0 0 7 0 0 0 0
6 0 0 1 9 5 0 0 0
0 9 8 0 4 2 0 6 7
8 0 0 0 6 0 0 0 3
4 2 0 8 5 3 0 9 1
7 0 0 9 2 0 0 0 6
0 6 0 5 3 7 2 8 4
2 0 7 4 1 9 6 3 5
0 0 0 0 8 6 1 7 9
sudokuUnsolved =
5 3 0 6 7 8 0 0 2
6 0 0 1 9 5 0 0 8
1 9 8 3 4 2 5 6 7
8 0 0 7 6 0 4 0 3
4 2 6 8 5 3 7 9 1
7 0 0 9 2 0 8 5 6
9 6 1 5 3 7 2 8 4
2 8 7 4 1 9 6 3 5
3 0 0 2 8 6 1 7 9
sudokuUnsolved =
5 3 4 6 7 8 9 1 2
6 0 2 1 9 5 3 4 8
1 9 8 3 4 2 5 6 7
8 0 0 7 6 1 4 2 3
4 2 6 8 5 3 7 9 1
7 1 3 9 2 4 8 5 6
9 6 1 5 3 7 2 8 4
2 8 7 4 1 9 6 3 5
3 0 5 2 8 6 1 7 9
sudokuUnsolved =
5 3 4 6 7 8 9 1 2
6 7 2 1 9 5 3 4 8
1 9 8 3 4 2 5 6 7
8 5 9 7 6 1 4 2 3
4 2 6 8 5 3 7 9 1
7 1 3 9 2 4 8 5 6
9 6 1 5 3 7 2 8 4
2 8 7 4 1 9 6 3 5
3 4 5 2 8 6 1 7 9
>>
Which we can compare to the actual solution -
Now the next step is to make a simple character recognition interface that enables a mobile device to automatically look at a puzzle and give solution in real-time.
Source:
Wikipedia Sudoku Page: https://en.wikipedia.org/wiki/Sudoku
First of all lets have a look at a typical Sudoku puzzle and some basic rules:
Sudoku Puzzle |
Yes - it has got everything to do with numbers!! lots of numbers!
A Sudoku puzzle typically has 81 boxes where each box can have a number between 1 to 9. However, all these boxes follow some rules that make it all interesting. You may have noticed 3x3 squares grouping the number boxes. A correct solution of Sudoku ensures no repetition of numbers from 1 to 9 inside each of the 3x3 squares, in each horizontal line and each vertical line. When solving a Sudoku puzzle, this is exactly where I look for a solution, and exactly where my thought process starts for my Sudoku solver algorithm.
I formed a set of rules that my algorithm should follow to look for possible solutions. I explain each rule with the thought process.
Rule # 1 - Boxes in a Square
Sudoku 3x3 Square |
In a typical Sudoku puzzle some number boxes are already filled in to give the solver some clues. Looking at a 3x3 square we know that it must contain the number 1 to 9 without repetition.
Rule # 2 - Horizontal Lines
Sudoku Horizontal Line |
Similar to 3x3 Squares, a horizontal line in a Sudoku puzzle has some clues - where the numbers from 1 to 9 appear without repetition.
Rule # 3 - Vertical Lines
Sudoku Vertical Line |
Boxes in vertical line also contain number from 1 to 9 - without repetition. This along with the previous two rules provides the key for the algorithm design.
Notice each of the above rules are clear, concise and can be easily translated into simple algorithm. Can you check what numbers are missing in a line? or a square? Yes - and there could be a number of ways to approach this..
The algorithm
The code I wrote uses the above three rules directly to look for possible solutions within a Sudoku puzzle. Of course, as every algorithm, my Sudoku solver comes with its own limitations. It assumes that at a given stage application of rules 1, 2 and 3 will always result in one or more than one solvable number box(es).
Sudoku Solver working for a given unsolved box |
For a given unsolved box, the proposed algorithm applies rule 1, 2 and 3 to collect the available clues. After which, a solution occurs only if there is just one number between 1 to 9 that remains unassigned. The algorithm iterates a few times with this algorithm and thats it!! It essentially does exactly what a typical Sudoku solving person would do - which is fascinating and extremely simple to transform into a working code.
Hashmaps to the rescue
To check for a possible solution I use my own version of hashmaps - this significantly makes the code easier. Instead of collecting all the clues in the three rules - I simply use a hashmap that maps the numbers from 1 to 9 onto a binary array indexed from 1 to 9. For solving each box, this binary hashmap array is first set to zeros - then with each clue the corresponding index mapping in the binary hashmap is set to 1. When all rules have been applied I then take the sum of hashmap - if it is equal to 8 - I have a solution!
Consider if we are looking for a possible solution at the following location
Initially the binary hashmap would be empty
While after application of three rules - it would represent the possible solution(s) - where the mapping of each clue is direct index in the hashmap and the given clues present are set to 1 - while all 0(s) represent the possible solution(s)
The awesome code
Now lets have a look at the code it self:
close all clear all clc % sudoku solver v 1 %% DATA Input sudokuSolved = [ 5 3 4 6 7 8 9 1 2; 6 7 2 1 9 5 3 4 8; 1 9 8 3 4 2 5 6 7; 8 5 9 7 6 1 4 2 3; 4 2 6 8 5 3 7 9 1; 7 1 3 9 2 4 8 5 6; 9 6 1 5 3 7 2 8 4; 2 8 7 4 1 9 6 3 5; 3 4 5 2 8 6 1 7 9]; sudokuUnknownValues = [ 0 0 1 1 0 1 1 1 1; 0 1 1 0 0 0 1 1 1; 1 0 0 1 1 1 1 0 1; 0 1 1 1 0 1 1 1 0; 0 1 1 0 1 0 1 1 0; 0 1 1 1 0 1 1 1 0; 1 0 1 1 1 1 0 0 1; 1 1 1 0 0 0 1 1 0; 1 1 1 1 0 1 1 0 0]; sudokuUnsolved = sudokuSolved .* (~sudokuUnknownValues); %% while(sum(sum(sudokuUnsolved)) ~=405) for i = 1:size(sudokuUnsolved, 2) for j = 1:size(sudokuUnsolved,1) if(sudokuUnsolved(j, i)==0) % if unknown value then perform three checks curSolve = zeros(1,9); % check col cCol = sudokuUnsolved(:,i)'; for c = 1:9 if(cCol(c) ~= 0) curSolve(cCol(c)) = 1; end end % check row cRow = sudokuUnsolved(j,:); for r = 1:9 if(cRow(r) ~= 0) curSolve(cRow(r)) = 1; end end % check square cRow = 1+ floor((j-1)/3)*3; cCol = 1+ floor((i-1)/3)*3; for cR = cRow:cRow+2 for cC = cCol:cCol+2 if(sudokuUnsolved(cR, cC) ~= 0) curSolve(sudokuUnsolved(cR, cC)) =1; end end end solvedVal = 0; if(sum(curSolve) == 8) for cC = 1:9 if(curSolve(cC) == 0) solvedVal = cC; end end end sudokuUnsolved(j,i) = solvedVal; end end end sudokuUnsolved end
and the solution of the above sudoku puzzle:
sudokuUnsolved =
5 3 0 0 7 0 0 0 0
6 0 0 1 9 5 0 0 0
0 9 8 0 0 0 0 6 0
8 0 0 0 6 0 0 0 3
4 0 0 8 5 3 0 0 1
7 0 0 0 2 0 0 0 6
0 6 0 0 3 7 2 8 4
0 0 0 4 1 9 0 3 5
0 0 0 0 8 0 0 7 9
sudokuUnsolved =
5 3 0 0 7 0 0 0 0
6 0 0 1 9 5 0 0 0
0 9 8 0 4 2 0 6 7
8 0 0 0 6 0 0 0 3
4 2 0 8 5 3 0 9 1
7 0 0 9 2 0 0 0 6
0 6 0 5 3 7 2 8 4
2 0 7 4 1 9 6 3 5
0 0 0 0 8 6 1 7 9
sudokuUnsolved =
5 3 0 6 7 8 0 0 2
6 0 0 1 9 5 0 0 8
1 9 8 3 4 2 5 6 7
8 0 0 7 6 0 4 0 3
4 2 6 8 5 3 7 9 1
7 0 0 9 2 0 8 5 6
9 6 1 5 3 7 2 8 4
2 8 7 4 1 9 6 3 5
3 0 0 2 8 6 1 7 9
sudokuUnsolved =
5 3 4 6 7 8 9 1 2
6 0 2 1 9 5 3 4 8
1 9 8 3 4 2 5 6 7
8 0 0 7 6 1 4 2 3
4 2 6 8 5 3 7 9 1
7 1 3 9 2 4 8 5 6
9 6 1 5 3 7 2 8 4
2 8 7 4 1 9 6 3 5
3 0 5 2 8 6 1 7 9
sudokuUnsolved =
5 3 4 6 7 8 9 1 2
6 7 2 1 9 5 3 4 8
1 9 8 3 4 2 5 6 7
8 5 9 7 6 1 4 2 3
4 2 6 8 5 3 7 9 1
7 1 3 9 2 4 8 5 6
9 6 1 5 3 7 2 8 4
2 8 7 4 1 9 6 3 5
3 4 5 2 8 6 1 7 9
>>
Which we can compare to the actual solution -
Sudoku Example Solution - source Wikipedia |
Now the next step is to make a simple character recognition interface that enables a mobile device to automatically look at a puzzle and give solution in real-time.
Source:
Wikipedia Sudoku Page: https://en.wikipedia.org/wiki/Sudoku