Skip to content

Instantly share code, notes, and snippets.

@hayd
Created July 13, 2012 22:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hayd/3108041 to your computer and use it in GitHub Desktop.
Save hayd/3108041 to your computer and use it in GitHub Desktop.
Sudoku checker (JS)- checks whether a sudoku grid is allowable, or completable (and if so fills it in)
//This is a conversion from a Python file to JavaScript (from https://gist.github.com/3097993)
//It's in progress (by which I mean: completely untest).
function set(list){
/*
* returns list with no repeated entries
*/
var set_list = [];
for (var element in list){
if (!(element in set_list)){
set_list.push(element);
}
}
return set_list;
}
function range(start, stop, step){
/*
* A pythonic range function.
*
* Thanks to Tardeck on StackOverflow (http://stackoverflow.com/a/8273091)
*/
if (typeof stop=='undefined'){
// one param defined
stop = start;
start = 0;
}
if (typeof step=='undefined'){
step = 1;
}
if ((step>0 && start>=stop) || (step<0 && start<=stop)){
return [];
}
var result = [];
for (var i=start; step>0 ? i<stop : i>stop; i+=step){
result.push(i);
}
return result;
}
function check_sudoku(grid){
/**
* If grid is a valid sudoku board, so far filled-in correctly: returns true
* else if grid is a valid sudoku board but has been filled-in incorrectly: returns false
* else: returns null
*
* Note: returning true does not imply there is a solution for grid, see solve_sudoku.
*/
function sanity_check(){
/**
* If grid is of the sudoku board format: returns true
* Else: returns null
*/
if (!( grid instanceof Array && grid.length === 9 )){
return null;
}
for (var row in grid){
if (!( row instanceof Array && row.length === 9 )){
return null;
}
for (var element in row){
if (!( element in range(10) && String(element).length === 1)){
return null;
}
}
}
return true;
}
function no_repeats_check(numbers){
return numbers.length === set(numbers).length;
}
function row_check(row){
var non_zero_in_row = [];
for (var col in range(9)){
if (grid[row][col] !==0){
non_zero_in_col.push(grid[row][col]);
}
}
return no_repeats_check(non_zero_in_row);
}
function col_check(col){
var non_zero_in_col = [];
for (var row in range(9)){
if (grid[row][col] !==0){
non_zero_in_col.push(grid[row][col]);
}
}
return no_repeats_check(non_zero_in_col);
}
function square_check(start_row, start_col){
var non_zero_in_square = [];
for (var row in range(start_row, start_row+3)){
for (var col in range(start_col, start_col+3)){
if (grid[row][col] !== 0){
non_zero_in_square.push(grid[row][col]);
}
}
}
return no_repeats_check(non_zero_in_square);
}
if (! sanity_check()){
return null;
}
for (var row in range(9)){
if (! row_check(row)){
return false;
}
}
for (var col in range(9)){
if (! col_check(col)){
return false;
}
}
for (var start_row in range(0,9,3)){
for (var start_col in range(0,9,3)){
if (!square_check(start_row,start_col)){
return false;
}
}
}
return true;
}
function solve_sudoku(grid){
/**
* If grid is a valid board and it can be completed: returns an example completed grid
* Else if grid is a valid board, but there are no possible solutions: returns false
* Else: returns null
*/
var check_grid = check_sudoku(grid);
if (! check_grid){
return check_grid;
}
//recursion on the empty squares
for (var row in range(9)){
for (var col in range(9)){
if (grid[row][col] === 0){
//this is the first empty square
for (var k in range(1,10)){
grid[row][col] = k;
var solved = solve_sudoku(grid);
if (solved){
//we've found a solution recursively
return solved;
}
//reset the empty square, there's no way to fill it in.
grid[row][col] = 0;
return false;
}
}
}
}
//there are no empty squares and check_sudoku is true, so grid is a solution.
return grid;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment