Last active
July 6, 2017 22:17
-
-
Save tuxsudo/04a7243ec848e1a7a4ce11c488e38498 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const myPuzzle = [ | |
1, null, 9, null, null, null, null, 6, null, | |
5, 3, null, null, 7, null, null, null, null, | |
null, null, 4, null, 2, 6, null, null, null, | |
null, 5, null, null, null, null, null, null, 4, | |
null, 7, null, 6, 3, 4, null, 2, null, | |
6, null, null, null, null, null, null, 7, null, | |
null, null, null, 7, 4, null, 9, null, null, | |
null, null, null, null, 1, null, null, 5, 2, | |
null, 9, null, null, null, null, 4, null, 3 | |
]; | |
const puzzleRowByRowIdx = (puzzle, i) => puzzle.slice(i*9, i*9+9); | |
const puzzleColByColIdx = (puzzle, i) => | |
[ puzzle[i], puzzle[i+9], puzzle[i+18], puzzle[i+27], puzzle[i+36], puzzle[i+45], puzzle[i+54], puzzle[i+63], puzzle[i+72] ]; | |
const puzzleSquareBySquareIdx = (puzzle, i) => { | |
const cell0 = [0,3,6,27,30,33,54,57,60][i]; | |
return [ | |
puzzle[cell0], puzzle[cell0+1], puzzle[cell0+2], | |
puzzle[cell0+9], puzzle[cell0+10], puzzle[cell0+11], | |
puzzle[cell0+18], puzzle[cell0+19], puzzle[cell0+20] | |
]; | |
} | |
const validateGroup = (group=[]) => | |
group | |
.reduce( | |
(acc, num, idx, nums) => acc && (num===null||nums.indexOf(num)===idx), | |
true | |
); | |
const validatePuzzle = puzzle => { | |
for(let i = 0; i < 9; i++) { | |
const rowIsValid = validateGroup(puzzleRowByRowIdx(puzzle, i)); | |
if(!rowIsValid) { | |
return false; | |
} | |
const colIsValid = validateGroup(puzzleColByColIdx(puzzle, i)); | |
if(!colIsValid) { | |
return false; | |
} | |
const squareIsValid = validateGroup(puzzleSquareBySquareIdx(puzzle, i)); | |
if(!squareIsValid) { | |
return false; | |
} | |
} | |
return true; | |
} | |
const checkPuzzleCompletion = puzzle => | |
puzzle.filter(x=>x).length===81; | |
const solve = (puzzle, cell = 0, tryWith = 1) => { | |
// set recursion bounds | |
if(cell > 80) { | |
return false; | |
} | |
if( checkPuzzleCompletion(puzzle) ) { | |
return validatePuzzle(puzzle) | |
? puzzle | |
: false; | |
} | |
const value = puzzle[cell]; | |
// move to next empty cell if already a number in current cell... | |
if(value!==null) { | |
return solve(puzzle, cell+1); | |
} | |
let attempt = [].concat(puzzle); | |
attempt[cell] = tryWith; | |
const isValid = validatePuzzle(attempt); | |
if(isValid) { | |
const solved = solve(attempt, cell+1); | |
if(solved) { | |
return solved; | |
} | |
} | |
// not valid with current attempt, or unsolveable branch... | |
if(tryWith < 9) { | |
return solve(puzzle, cell, tryWith+1); | |
} | |
return false; | |
} | |
console.log( solve(myPuzzle) ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment