top of page

Making a Sudoku Puzzle Solver

  • Yanfeng Liu
  • Sep 5, 2016
  • 4 min read

Sudoku is a traditional number game that requires the 1~9 to be put on a 9 by 9 grid such that on every row, every column, and every 3 by 3 block there is exactly one of each number. Usually people solve this as a hobby to kill time, but have you thought about giving a computer the power to solve all possible Soduku puzzles in only a fraction of a second?

The advantage of computer over human brains is that a computer can check millions of possibilities per second. Even though computer is not so good at reasoning or imagining things like we do, we can still teach computers to think in a different way to fully use their computing power. In the case of this Sudoku puzzle solver, we first scan the board to see what numbers are already on it, and then we enter a while loop to iteratively solve the it piece by piece until the entire board is filled with correct numbers.

The while loop is as following:

  • for each cell, check if it is already filled

  • if it is, then remember what number is filled

  • if not, check the row, the column, and the 3 by 3 block to see what valid numbers can be filled in

  • if there is only one valid number for that cell, then fill it in

  • check if the cell is the only one in the 3 by 3 block that has a certain valid number

  • check if the cell is the only one in the row that has a certain valid number

  • check if the cell is the only one in the column that has a certain valid number

  • update valid candidates for each cell

  • repeat

And the result:

The MATLAB code is as following:

%% take board as an input (just an example)

board = [

0 0 6 0 3 0 0 0 9;

7 8 0 0 2 0 6 4 3;

0 9 0 4 0 0 1 0 0;

0 0 0 0 0 7 0 0 8;

0 0 3 0 0 0 7 0 0;

6 0 0 3 0 0 0 0 0;

0 0 8 0 0 9 0 6 0;

1 6 9 0 7 0 0 8 4;

4 0 0 0 5 0 3 0 0]

original = board;

%% solve board

tic;

allValid = zeros(9, 9) + 1;

boardValid = zeros(9, 9);

iteration = 0;

usableNum = zeros(9, 9, 9);

while(sum(sum(boardValid == allValid)) ~= 81)

iteration = iteration + 1;

fprintf('Iteration %d\n', iteration);

for i = 1:9

for j = 1:9

blockX = ceil(i/3);

blockY = ceil(j/3);

index = 1;

usableNum(i, j, :) = 0;

% if (i, j) is filled, then it is done

if (board(i, j) ~= 0)

boardValid(i, j) = 1;

else

% if (i, j) is empty, find all valid numbers for it

for num = 1:9

if((checkValidity(board, num, i, j) == 1))

usableNum(i, j, index) = num;

index = index + 1;

end

end

% check if (i, j) has only one valid number

if (index == 2)

board(i, j) = usableNum(i, j, 1);

%fprintf('Using single candidate at %d %d\n', i, j);

% update valid numbers

% itself

usableNum(i, j, :) = 0;

% row

rowUsable = usableNum(i, :, :);

rowUsable(find(rowUsable == num)) = 0;

usableNum(i, :, :) = rowUsable;

% column

columnUsable = usableNum(:, j, :);

columnUsable(find(columnUsable == num)) = 0;

usableNum(:, j, :) = columnUsable;

% block

blockUsable = usableNum(((blockX-1)*3 + 1):((blockX-1)*3 + 3), ((blockY-1)*3 + 1):((blockY-1)*3 + 3), :);

blockUsable(find(blockUsable == num)) = 0;

usableNum(((blockX-1)*3 + 1):((blockX-1)*3 + 3), ((blockY-1)*3 + 1):((blockY-1)*3 + 3), :) = blockUsable;

end

if(iteration > 5)

% check if (i, j) is the only cell in the block that has a

% certain valid number

for r = 1:9

block = board(((blockX-1)*3 + 1):((blockX-1)*3 + 3), ((blockY-1)*3 + 1):((blockY-1)*3 + 3));

blockUsable = usableNum(((blockX-1)*3 + 1):((blockX-1)*3 + 3), ((blockY-1)*3 + 1):((blockY-1)*3 + 3), :);

if(checkBlock(block, blockUsable, r, i-(blockX-1)*3, j-(blockY-1)*3) == 1)

board(i, j) = r;

% update valid numbers

% itself

usableNum(i, j, :) = 0;

% row

rowUsable = usableNum(i, :, :);

rowUsable(find(rowUsable == r)) = 0;

usableNum(i, :, :) = rowUsable;

% column

columnUsable = usableNum(:, j, :);

columnUsable(find(columnUsable == r)) = 0;

usableNum(:, j, :) = columnUsable;

end

end

% check if (i, j) is the only cell in the row that has a

% certain valid number

for r = 1:9

if (checkRow(board(i, :), usableNum(i, :, :), r, j) == 1)

board(i, j) = r;

% update valid numbers

% it self

usableNum(i, j, :) = 0;

% column

columnUsable = usableNum(:, j, :);

columnUsable(find(columnUsable == r)) = 0;

usableNum(:, j, :) = columnUsable;

% block

blockUsable = usableNum(((blockX-1)*3 + 1):((blockX-1)*3 + 3), ((blockY-1)*3 + 1):((blockY-1)*3 + 3), :);

blockUsable(find(blockUsable == r)) = 0;

usableNum(((blockX-1)*3 + 1):((blockX-1)*3 + 3), ((blockY-1)*3 + 1):((blockY-1)*3 + 3), :) = blockUsable;

end

end

% check if (i, j) is the only cell in the column that has a

% certain valid number

for r = 1:9

if (checkColumn(board(:, j), usableNum(:, j, :), r, i) == 1)

board(i, j) = r;

% update valid numbers

% itself

usableNum(i, j, :) = 0;

% row

rowUsable = usableNum(i, :, :);

rowUsable(find(rowUsable == r)) = 0;

usableNum(i, :, :) = rowUsable;

% block

blockUsable = usableNum(((blockX-1)*3 + 1):((blockX-1)*3 + 3), ((blockY-1)*3 + 1):((blockY-1)*3 + 3), :);

blockUsable(find(blockUsable == r)) = 0;

usableNum(((blockX-1)*3 + 1):((blockX-1)*3 + 3), ((blockY-1)*3 + 1):((blockY-1)*3 + 3), :) = blockUsable;

end

end

end

end

end

end

sum(sum(boardValid))

end

elapsedTime = toc;

%% display results

figure;

hold on;

l = 5;

for i = 0:8

for j = 0:8

rectangle('Position', [i*l, j*l, l, l], 'LineWidth', 3)

txt = sprintf('%d', board(9-j, i+1));

text(i*l + l/2, j*l + l/2, txt, 'HorizontalAlignment', 'right', 'FontSize', 20);

end

end

hold off;

txt = sprintf('Time: %.2f s', elapsedTime);

h = msgbox(txt);

ah = get( h, 'CurrentAxes' );

ch = get( ah, 'Children' );

set( ch, 'FontSize', 20 );

figure;

hold on;

for i = 0:8

for j = 0:8

rectangle('Position', [i*l, j*l, l, l], 'LineWidth', 3)

txt = sprintf('%d', original(9-j, i+1));

if(original(9-j, i+1) ~= 0)

text(i*l + l/2, j*l + l/2, txt, 'HorizontalAlignment', 'right', 'FontSize', 20);

end

end

end

ความคิดเห็น


Recent Posts
Archive
Search By Tags
Follow Us
  • Facebook Basic Square
  • Twitter Basic Square
  • Google+ Basic Square
bottom of page