-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathjs-backtracking-knight-movement.js
155 lines (125 loc) · 3.95 KB
/
js-backtracking-knight-movement.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// Knight Tour problem
// GOAL:
// knight on the top-left corner (0)
// should jump to
// all squares
// on chess board / (8x8) matrix
/*
0 59 38 33 30 17 8 63
37 34 31 60 9 62 29 16
58 1 36 39 32 27 18 7
35 48 41 26 61 10 15 28
42 57 2 49 40 23 6 19
47 50 45 54 25 20 11 14
56 43 52 3 22 13 24 5
51 46 55 44 53 4 21 12
*/
class KnightTour {
//
constructor() {
//
this.N = 8;
this.aa = Array.from({ length: this.N }, () => new Array(this.N));
// next moves/ (x, y) coordinates of Knight
this.xMoves = [2, 1, -1, -2, -2, -1, 1, 2];
this.yMoves = [1, 2, 2, 1, -1, -2, -2, -1];
/*
x,y
1,-2 2,1
-1,-2 1,2
-2,-1 -1,2
-2,1
*/
}
isSafe(x, y) {
return (
x >= 0 && //
x < this.N &&
y >= 0 &&
y < this.N &&
this.aa[x][y] == -1
);
}
// returns fals e, if no complete tour is possible,
// return tru e, prints the tour.
// multiple solutions may exist - after 1 solution found, exit
solveKT() {
//
for (let x = 0; x < this.N; x++) {
for (let y = 0; y < this.N; y++) {
this.aa[x][y] = -1;
}
}
// Knight is initially at the first block
this.aa[0][0] = 0;
/*
0 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1
*/
// start from 0,0 and explore all tours
if (this.solveKTUtil(0, 0, 1)) {
this.printSolution();
} else {
console.log("Solution does not exist");
}
}
solveKTUtil(x, y, movei) {
if (movei == this.N * this.N) return true;
// try all next moves from the current x, y
for (let k = 0; k < this.N; k++) {
//
let next_x = x + this.xMoves[k];
let next_y = y + this.yMoves[k];
if (this.isSafe(next_x, next_y)) {
//
this.aa[next_x][next_y] = movei;
/*
// final solution will be
0 59 38 33 30 17 8 63
37 34 31 60 9 62 29 16
58 1 36 39 32 27 18 7
35 48 41 26 61 10 15 28
42 57 2 49 40 23 6 19
47 50 45 54 25 20 11 14
56 43 52 3 22 13 24 5
51 46 55 44 53 4 21 12
*/
if (this.solveKTUtil(next_x, next_y, movei + 1)) {
// solution is complete
return true;
} else {
// backtracking - goto prev stage
this.aa[next_x][next_y] = -1;
}
}
}
return false;
}
printSolution() {
let str = "";
for (let x = 0; x < this.N; x++) {
str = "";
for (let y = 0; y < this.N; y++) str += this.aa[x][y] + " ";
console.log(str);
}
}
}
let a = new KnightTour();
a.solveKT();
/*
Time Complexity looks like:
- 1st move 8 possibilities
- From 2nd move <=7 possibilities, since we don't go back to same position.
-- There are 63 moves like 2nd move.
8 * 7 * 7 * ... * 7 (*7 is for 63 times)
= 8 * (7 ^ 63)
= 8 * (8-1) ^(64-1)
= 8 * (8-1) ^(r*c-1)
= 8 ^ (r*c) approx -- r and c are # of rows & columns of matrix
*/