Skip to content

Instantly share code, notes, and snippets.

@ntatko
Created August 17, 2023 21:43
Show Gist options
  • Select an option

  • Save ntatko/04bcacfb6ce3e12daac23b33ff0fed79 to your computer and use it in GitHub Desktop.

Select an option

Save ntatko/04bcacfb6ce3e12daac23b33ff0fed79 to your computer and use it in GitHub Desktop.
Sample sudoku solver
const floor3 = (n) => {
if (n%3 === 0) {
return n
}
return floor3(n - 1)
}
// Class to help keep track of the proper order of things.
class Sudoku {
constructor (puzzle, annotations) {
this.puzzle = puzzle
this.originalPuzzle = puzzle
this.annotations = annotations
this.originalAnnotations = annotations
}
get isUnchanged () {
return deepEqual(this.annotations, this.originalAnnotations) && deepEqual(this.puzzle, this.originalPuzzle)
}
post () { return [this.puzzle, this.annotations]; }
getRow(n) { return this.puzzle[n]; }
getColumn(n) { return this.puzzle.map(row => row[n]); }
getSquare(i, j) {
const is = [floor3(i), floor3(i) + 1, floor3(i) + 2]
const js = [floor3(j), floor3(j) + 3]
return is.map(rowIndex => this.puzzle[rowIndex].slice(...js)).reduce((acc, rowBits) => [...acc, ...rowBits], [])
}
getRowAnnotations(n) { return this.annotations[n] }
getColumnAnnotations(n) { return this.annotations.map(row => row[n])}
getSquareAnnotations(i, j) {
const is = [floor3(i), floor3(i) + 1, floor3(i) + 2]
const js = [floor3(j), floor3(j) + 3]
return is.map(rowIndex => this.annotations[rowIndex].slice(...js)).reduce((acc, rowBits) => [...acc, ...rowBits], [])
}
}
const getAnnotationCountOf = (annotations, n) => {
return annotations.reduce((all, cellAnnotations) => {
return [...all, ...cellAnnotations]
}).filter(ann => ann === n).length
}
const annotate = (puzzle) => {
const annotations = puzzle.puzzle.map((row, i) => {
return row.map((cell, j) => {
if (cell !== 0) {
return []
}
const possibles = [1, 2, 3, 4, 5, 6, 7, 8, 9]
const row = puzzle.getRow(i)
const column = puzzle.getColumn(j)
const square = puzzle.getSquare(i, j)
const remaining = [...row, ...column, ...square].reduce((acc, num) => {
return acc.filter(n => n !== num)
}, possibles)
return remaining
})
})
puzzle.annotations = annotations
puzzle.puzzle.forEach((row, i) => {
row.forEach((cell, j) => {
if (cell === 0 && puzzle.annotations[i][j].length === 1) {
puzzle.puzzle[i][j] = puzzle.annotations[i][j][0]
} else if (puzzle.annotations[i][j].length > 1) {
puzzle.annotations[i][j].find(annotation => {
const rowCount = getAnnotationCountOf(puzzle.getRowAnnotations(i), annotation)
const columnCount = getAnnotationCountOf(puzzle.getColumnAnnotations(j), annotation)
const squareCount = getAnnotationCountOf(puzzle.getSquareAnnotations(i, j), annotation)
if ([rowCount, columnCount, squareCount].includes(1)) {
puzzle.puzzle[i][j] = annotation
}
})
}
})
})
}
const loop = (currentPuzzle, currentAnnotations) => {
const sudokuPuzzle = new Sudoku(currentPuzzle, currentAnnotations)
annotate(sudokuPuzzle)
return sudokuPuzzle.post()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment