Skip to content

Commit 72d0a47

Browse files
committed
[Algorithm Design and Techniques]
1 parent b617530 commit 72d0a47

File tree

4 files changed

+201
-0
lines changed

4 files changed

+201
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
export function ratInAMaze(maze: Array<Array<number>>) {
2+
const solution: Array<Array<number>> = [];
3+
4+
for (let i = 0; i < maze.length; i++) {
5+
solution[i] = [];
6+
for (let j = 0; j < maze[i].length; j++) {
7+
solution[i][j] = 0;
8+
}
9+
}
10+
11+
if (findPath(maze, 0, 0, solution) === false) {
12+
return solution;
13+
} else {
14+
return 'NO PATH FOUND';
15+
}
16+
}
17+
18+
function findPath(
19+
maze: Array<Array<number>>,
20+
x: number,
21+
y: number,
22+
solution: Array<Array<number>>
23+
) {
24+
const n = maze.length;
25+
// check if maze[x][y] is feasible to move
26+
if (x === n - 1 && y === n - 1) {
27+
// we have reached
28+
solution[x][y] = 1;
29+
return true;
30+
}
31+
32+
// Check if maze[x][y] is valid
33+
if (isSafe(maze, x, y) === true) {
34+
// mark x,y as part of solution path
35+
solution[x][y] = 1;
36+
37+
/* Move forward in x direction */
38+
if (findPath(maze, x + 1, y, solution)) {
39+
return true;
40+
}
41+
42+
/* If moving in x direction doesn't give
43+
solution then Move down in y direction */
44+
if (findPath(maze, x, y + 1, solution)) {
45+
return true;
46+
}
47+
48+
/* If none of the above movements work then
49+
BACKTRACK: unmark x,y as part of solution
50+
path */
51+
solution[x][y] = 0;
52+
return false;
53+
}
54+
55+
return false;
56+
}
57+
58+
function isSafe(maze: Array<Array<number>>, x: number, y: number) {
59+
const n = maze.length;
60+
// check if x and y are in limits and cell is not blocked
61+
if (x >= 0 && y >= 0 && x < n && y < n && maze[x][y] !== 0) {
62+
return true;
63+
}
64+
return false;
65+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
const UNASSIGNED = 0;
2+
3+
export function sudokuSolver(grid: Array<Array<number>>) {
4+
if (solveSudoku(grid) === true) {
5+
return grid;
6+
} else {
7+
return 'NO SOLUTION EXISTS!';
8+
}
9+
}
10+
11+
function solveSudoku(grid: Array<Array<number>>) {
12+
let row = 0;
13+
let col = 0;
14+
let checkBlankSpaces = false;
15+
16+
// If there is no unassigned location, we are done
17+
for (row = 0; row < grid.length; row++) {
18+
for (col = 0; col < grid[row].length; col++) {
19+
if (grid[row][col] === UNASSIGNED) {
20+
checkBlankSpaces = true;
21+
break;
22+
}
23+
}
24+
if (checkBlankSpaces === true) {
25+
break;
26+
}
27+
}
28+
29+
if (checkBlankSpaces === false) {
30+
return true;
31+
} // success!
32+
33+
// consider digits 1 to 9
34+
for (let num = 1; num <= 9; num++) {
35+
// if looks promising
36+
if (isSafe(grid, row, col, num)) {
37+
// make tentative assignment
38+
grid[row][col] = num;
39+
40+
// return, if success, yay!
41+
if (solveSudoku(grid)) {
42+
return true;
43+
}
44+
45+
// failure, unmake & try again
46+
grid[row][col] = UNASSIGNED;
47+
}
48+
}
49+
50+
return false;
51+
}
52+
53+
/* Returns a boolean which indicates whether any assigned entry
54+
in the specified row matches the given number. */
55+
function usedInRow(grid: Array<Array<number>>, row: number, num: number) {
56+
for (let col = 0; col < grid.length; col++) {
57+
if (grid[row][col] === num) {
58+
return true;
59+
}
60+
}
61+
return false;
62+
}
63+
64+
/* Returns a boolean which indicates whether any assigned entry
65+
in the specified column matches the given number. */
66+
function usedInCol(grid: Array<Array<number>>, col: number, num: number) {
67+
for (let row = 0; row < grid.length; row++) {
68+
if (grid[row][col] === num) {
69+
return true;
70+
}
71+
}
72+
return false;
73+
}
74+
75+
/* Returns a boolean which indicates whether any assigned entry
76+
within the specified 3x3 box matches the given number. */
77+
function usedInBox(
78+
grid: Array<Array<number>>,
79+
boxStartRow: number,
80+
boxStartCol: number,
81+
num: number
82+
) {
83+
for (let row = 0; row < 3; row++) {
84+
for (let col = 0; col < 3; col++) {
85+
if (grid[row + boxStartRow][col + boxStartCol] === num) {
86+
return true;
87+
}
88+
}
89+
}
90+
return false;
91+
}
92+
93+
/* Returns a boolean which indicates whether it will be legal to assign
94+
num to the given row,col location. */
95+
function isSafe(grid: Array<Array<number>>, row: number, col: number, num: number) {
96+
/* Check if 'num' is not already placed in current row,
97+
current column and current 3x3 box */
98+
return (
99+
!usedInRow(grid, row, num) &&
100+
!usedInCol(grid, col, num) &&
101+
!usedInBox(grid, row - row % 3, col - col % 3, num)
102+
);
103+
}

src/ts/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ export { findMinValue as findMinValue } from './algorithms/search/min-max-search
6363
// chapter 14
6464
export { binarySearch as binarySearchRecursive } from './algorithms/search/binary-search-recursive';
6565
export { minCoinChange as minCoinChange } from './algorithms/dynamic-programing/min-coin-change';
66+
export { ratInAMaze as ratInAMaze } from './algorithms/backtracking/rat-in-maze';
67+
export { sudokuSolver as sudokuSolver } from './algorithms/backtracking/sudoku-solver';
6668

6769

6870
/* import { hotPotato } from './others/hot-potato';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import 'mocha';
2+
import { expect } from 'chai';
3+
import { sudokuSolver } from '../../../../src/ts/index';
4+
5+
describe('Sudoku Solver', () => {
6+
it('sudoku solver', () => {
7+
const grid = [
8+
[3, 0, 6, 5, 0, 8, 4, 0, 0],
9+
[5, 2, 0, 0, 0, 0, 0, 0, 0],
10+
[0, 8, 7, 0, 0, 0, 0, 3, 1],
11+
[0, 0, 3, 0, 1, 0, 0, 8, 0],
12+
[9, 0, 0, 8, 6, 3, 0, 0, 5],
13+
[0, 5, 0, 0, 9, 0, 6, 0, 0],
14+
[1, 3, 0, 0, 0, 0, 2, 5, 0],
15+
[0, 0, 0, 0, 0, 0, 0, 7, 4],
16+
[0, 0, 5, 2, 0, 6, 3, 0, 0]
17+
];
18+
const solution = [
19+
[3, 1, 6, 5, 7, 8, 4, 9, 2],
20+
[5, 2, 9, 1, 3, 4, 7, 6, 8],
21+
[4, 8, 7, 6, 2, 9, 5, 3, 1],
22+
[2, 6, 3, 4, 1, 5, 9, 8, 7],
23+
[9, 7, 4, 8, 6, 3, 1, 2, 5],
24+
[8, 5, 1, 7, 9, 2, 6, 4, 3],
25+
[1, 3, 8, 9, 4, 7, 2, 5, 6],
26+
[6, 9, 2, 3, 5, 1, 8, 7, 4],
27+
[7, 4, 5, 2, 8, 6, 3, 1, 9]
28+
];
29+
expect(sudokuSolver(grid)).to.deep.equal(solution);
30+
});
31+
});

0 commit comments

Comments
 (0)