mirror of
https://github.com/TheAlgorithms/JavaScript.git
synced 2025-07-06 17:50:39 +08:00
78
Backtracking/KnightTour.js
Normal file
78
Backtracking/KnightTour.js
Normal file
@ -0,0 +1,78 @@
|
||||
// Wikipedia: https://en.wikipedia.org/wiki/Knight%27s_tour
|
||||
|
||||
class OpenKnightTour {
|
||||
constructor (size) {
|
||||
this.board = new Array(size).fill(0).map(() => new Array(size).fill(0))
|
||||
this.size = size
|
||||
}
|
||||
|
||||
getMoves ([i, j]) {
|
||||
// helper function to get the valid moves of the knight from the current position
|
||||
const moves = [
|
||||
[i + 2, j - 1],
|
||||
[i + 2, j + 1],
|
||||
[i - 2, j - 1],
|
||||
[i - 2, j + 1],
|
||||
[i + 1, j - 2],
|
||||
[i + 1, j + 2],
|
||||
[i - 1, j - 2],
|
||||
[i - 1, j + 2]
|
||||
]
|
||||
|
||||
return moves.filter(([y, x]) => y >= 0 && y < this.size && x >= 0 && x < this.size)
|
||||
}
|
||||
|
||||
isComplete () {
|
||||
// helper function to check if the board is complete
|
||||
return !this.board.map(row => row.includes(0)).includes(true)
|
||||
}
|
||||
|
||||
solve () {
|
||||
// function to find the solution for the given board
|
||||
for (let i = 0; i < this.size; i++) {
|
||||
for (let j = 0; j < this.size; j++) {
|
||||
if (this.solveHelper([i, j], 0)) return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
solveHelper ([i, j], curr) {
|
||||
// helper function for the main computation
|
||||
if (this.isComplete()) return true
|
||||
|
||||
for (const [y, x] of this.getMoves([i, j])) {
|
||||
if (this.board[y][x] === 0) {
|
||||
this.board[y][x] = curr + 1
|
||||
if (this.solveHelper([y, x], curr + 1)) return true
|
||||
// backtracking
|
||||
this.board[y][x] = 0
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
printBoard () {
|
||||
// utility function to display the board
|
||||
for (const row of this.board) {
|
||||
let string = ''
|
||||
for (const elem of row) {
|
||||
string += elem + '\t'
|
||||
}
|
||||
console.log(string)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function main () {
|
||||
const board = new OpenKnightTour(5)
|
||||
|
||||
board.printBoard()
|
||||
console.log('\n')
|
||||
|
||||
board.solve()
|
||||
|
||||
board.printBoard()
|
||||
}
|
||||
|
||||
main()
|
65
Backtracking/NQueen.js
Normal file
65
Backtracking/NQueen.js
Normal file
@ -0,0 +1,65 @@
|
||||
class NQueen {
|
||||
constructor (size) {
|
||||
this.board = new Array(size).fill('.').map(() => new Array(size).fill('.'))
|
||||
this.size = size
|
||||
}
|
||||
|
||||
isValid ([row, col]) {
|
||||
// function to check if the placement of the queen in the given location is valid
|
||||
|
||||
// checking the left of the current row
|
||||
for (let i = 0; i < col; i++) {
|
||||
if (this.board[row][i] === 'Q') return false
|
||||
}
|
||||
|
||||
// checking the upper left diagonal
|
||||
for (let i = row, j = col; i >= 0 && j >= 0; i--, j--) {
|
||||
if (this.board[i][j] === 'Q') return false
|
||||
}
|
||||
|
||||
// checking the lower left diagonal
|
||||
for (let i = row, j = col; j >= 0 && i < this.size; i++, j--) {
|
||||
if (this.board[i][j] === 'Q') return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
solve (col = 0) {
|
||||
// function to solve the board
|
||||
if (col >= this.size) { return true }
|
||||
|
||||
for (let i = 0; i < this.size; i++) {
|
||||
if (this.isValid([i, col])) {
|
||||
this.board[i][col] = 'Q'
|
||||
|
||||
if (this.solve(col + 1)) { return true }
|
||||
|
||||
// backtracking
|
||||
this.board[i][col] = '.'
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
printBoard () {
|
||||
// utility function to display the board
|
||||
for (const row of this.board) {
|
||||
console.log(...row)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function main () {
|
||||
const board = new NQueen(8)
|
||||
|
||||
board.printBoard()
|
||||
console.log('\n')
|
||||
|
||||
board.solve()
|
||||
|
||||
board.printBoard()
|
||||
}
|
||||
|
||||
main()
|
97
Backtracking/Sudoku.js
Normal file
97
Backtracking/Sudoku.js
Normal file
@ -0,0 +1,97 @@
|
||||
class Sudoku {
|
||||
// Sudoku Class to hold the board and related functions
|
||||
constructor (board) {
|
||||
this.board = board
|
||||
}
|
||||
|
||||
findEmptyCell () {
|
||||
// Find a empty cell in the board (returns [-1, -1] if all cells are filled)
|
||||
for (let i = 0; i < 9; i++) {
|
||||
for (let j = 0; j < 9; j++) {
|
||||
if (this.board[i][j] === 0) return [i, j]
|
||||
}
|
||||
}
|
||||
return [-1, -1]
|
||||
}
|
||||
|
||||
check ([y, x], value) {
|
||||
// checks if the value to be added in the board is an acceptable value for the cell
|
||||
|
||||
// checking through the row
|
||||
for (let i = 0; i < 9; i++) {
|
||||
if (this.board[i][x] === value) return false
|
||||
}
|
||||
// checking through the column
|
||||
for (let i = 0; i < 9; i++) {
|
||||
if (this.board[y][i] === value) return false
|
||||
}
|
||||
|
||||
// checking through the 3x3 block of the cell
|
||||
const secRow = Math.floor(y / 3)
|
||||
const secCol = Math.floor(x / 3)
|
||||
for (let i = (secRow * 3); i < ((secRow * 3) + 3); i++) {
|
||||
for (let j = (secCol * 3); j < ((secCol * 3) + 3); j++) {
|
||||
if (y !== i && x !== j && this.board[i][j] === value) return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
solve () {
|
||||
const [y, x] = this.findEmptyCell()
|
||||
|
||||
// checking if the board is complete
|
||||
if (y === -1 && x === -1) return true
|
||||
|
||||
for (let val = 1; val < 10; val++) {
|
||||
if (this.check([y, x], val)) {
|
||||
this.board[y][x] = val
|
||||
if (this.solve()) return true
|
||||
// backtracking if the board cannot be solved using current configuration
|
||||
this.board[y][x] = 0
|
||||
}
|
||||
}
|
||||
// returning false the board cannot be solved using current configuration
|
||||
return false
|
||||
}
|
||||
|
||||
getSection (row, [start, end]) {
|
||||
return this.board[row].slice(start, end)
|
||||
}
|
||||
|
||||
printBoard () {
|
||||
// helper function to display board
|
||||
for (let i = 0; i < 9; i++) {
|
||||
if (i % 3 === 0 && i !== 0) console.log('- - - - - - - - - - - -')
|
||||
console.log(
|
||||
...this.getSection(i, [0, 3]), ' | ',
|
||||
...this.getSection(i, [3, 6]), ' | ',
|
||||
...this.getSection(i, [6, 9]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function main () {
|
||||
// main function with an example
|
||||
const sudokuBoard = new Sudoku([
|
||||
[3, 0, 6, 5, 0, 8, 4, 0, 0],
|
||||
[5, 2, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 8, 7, 0, 0, 0, 0, 3, 1],
|
||||
[0, 0, 3, 0, 1, 0, 0, 8, 0],
|
||||
[9, 0, 0, 8, 6, 3, 0, 0, 5],
|
||||
[0, 5, 0, 0, 9, 0, 6, 0, 0],
|
||||
[1, 3, 0, 0, 0, 0, 2, 5, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 7, 4],
|
||||
[0, 0, 5, 2, 0, 6, 3, 0, 0]
|
||||
])
|
||||
|
||||
sudokuBoard.printBoard()
|
||||
|
||||
console.log('\n')
|
||||
sudokuBoard.solve()
|
||||
|
||||
sudokuBoard.printBoard()
|
||||
}
|
||||
|
||||
main()
|
Reference in New Issue
Block a user