1
0
This repository has been archived on 2025-03-31. You can view files and clone it, but cannot push or open issues or pull requests.
js-sudoku-solver/coffee/SudokuSolver.class.coffee

106 lines
4.2 KiB
CoffeeScript

class @SudokuSolver
@uniqueAll: (board) ->
for r in [0...board.dim2] by 1
for c in [0...board.dim2] by 1
SudokuChecks.unique(board, r, c) if board.cellAt(r, c).getValue() isnt '.'
return true
# returns all cells for the square of the specified cell
@getSquareCellsForCell: (board, r, c) ->
sqrid = Math.floor(r / board.dim) * board.dim + Math.floor(c / board.dim)
return @getSquareCells(board, sqrid)
@getSquareCells: (board, squareid) ->
result = []
rb = Math.floor(squareid / board.dim) * board.dim # base row for square
cb = squareid % board.dim * board.dim # base col for square
for i in [0...board.dim2] by 1
result.push(board.cellAt(rb + Math.floor(i / board.dim), cb + (i % board.dim)))
return result
@getRowCells: (board, row) ->
result = []
for i in [0...board.dim2] by 1
result.push(board.cellAt(row, i))
return result
@getColCells: (board, col) ->
result = []
for i in [0...board.dim2] by 1
result.push(board.cellAt(i, col))
return result
@runAllRows: (board, func) ->
for i in [0...board.dim2] by 1 # walk all rows
rowcells = @getRowCells(board, i)
SudokuChecks[func](rowcells)
@runAllColumns: (board, func) ->
for i in [0...board.dim2] by 1 # walk all columns
colcells = @getColCells(board, i)
SudokuChecks[func](colcells)
@runAllSquares: (board, func) ->
for i in [0...board.dim2] by 1 # walk all squares
sqrcells = @getSquareCells(board, i)
SudokuChecks[func](sqrcells)
@runBothDiags: (board, func) ->
return if not board.checkDiags
diag1 = []
diag2 = []
for i in [0...board.dim2] by 1
diag1.push(board.cellAt(i, i))
diag2.push(board.cellAt(i, board.dim2-i-1))
SudokuChecks[func](diag1)
SudokuChecks[func](diag2)
@oneUnknownAll: (board) ->
cells = []
for r in [0...board.dim2] by 1
for c in [0...board.dim2] by 1
cells.push(board.cellAt(r, c))
SudokuChecks.oneUnknown(cells)
@onePlaceRow: (board) -> @runAllRows(board, 'onePlace')
@onePlaceColumn: (board) -> @runAllColumns(board, 'onePlace')
@onePlaceSquare: (board) -> @runAllSquares(board, 'onePlace')
@onePlaceDiag: (board) -> @runBothDiags(board, 'onePlace')
@twoValPlacesSquare: (board) -> @runAllSquares(board, 'twoValPlaces')
@twoValPlacesRow: (board) -> @runAllRows(board, 'twoValPlaces')
@twoValPlacesColumn: (board) -> @runAllColumns(board, 'twoValPlaces')
@twoValPlacesDiag: (board) -> @runBothDiags(board, 'twoValPlaces')
@solveBoard: (board) ->
checks =
'uniqueAll': 'Value must be unique in row, column' + if board.checkDiags then ', square and diagonales.' else ' and square.'
'onePlaceSquare': 'Value has only one place in square.'
'onePlaceRow': 'Value has only one place in row.'
'onePlaceColumn': 'Value has only one place in column.'
'onePlaceDiag': 'Value has only one place in diagonale.'
'twoValPlacesSquare': 'Only two possible places for pair in square.'
'twoValPlacesRow': 'Only two possible places for pair in row.'
'twoValPlacesColumn': 'Only two possible places for pair in column.'
'twoValPlacesDiag': 'Only two possible places for pair in diagonale.'
'oneUnknownAll': 'Only one possible value left.'
i = 1
while true
console.time('Checking board.')
board.resetChangeFlags()
description = ''
for c of checks
description = checks[c]
@[c](board)
break if board.hasChanged()
if board.hasChanged()
console.info('Board was changed by "%s".', description)
body = document.getElementsByTagName('body')
body[0].innerHTML += i + '. ' + description + '<br />'
board.print()
i++
console.timeEnd('Checking board.')
break unless board.hasChanged() && i<100
return 0