101 Logo
onenoughtone

Code Implementation

Knight Probability in Chessboard Implementation

Below is the implementation of the knight probability in chessboard:

solution.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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
/**
* Calculate the probability that the knight remains on the board after k moves.
* Dynamic Programming (3D) approach.
*
* @param {number} n - Size of the chessboard
* @param {number} k - Number of moves
* @param {number} row - Starting row
* @param {number} column - Starting column
* @return {number} - Probability that the knight remains on the board
*/
function knightProbability(n, k, row, column) {
// Define the possible knight moves
const directions = [
[-2, -1], [-2, 1], [-1, -2], [-1, 2],
[1, -2], [1, 2], [2, -1], [2, 1]
];
// Initialize DP array
// dp[m][r][c] = probability of the knight being at cell (r, c) after m moves
const dp = Array(k + 1).fill().map(() =>
Array(n).fill().map(() =>
Array(n).fill(0.0)
)
);
// Base case: the knight is at the starting position with 100% probability after 0 moves
dp[0][row][column] = 1.0;
// Fill DP array
for (let m = 1; m <= k; m++) {
for (let r = 0; r < n; r++) {
for (let c = 0; c < n; c++) {
// For each possible knight move
for (const [dr, dc] of directions) {
// Calculate the previous position
const prevRow = r - dr;
const prevCol = c - dc;
// If the previous position is valid (on the board)
if (prevRow >= 0 && prevRow < n && prevCol >= 0 && prevCol < n) {
// Add the probability of the knight being at the previous position
// divided by 8 (since there are 8 possible moves, each with equal probability)
dp[m][r][c] += dp[m - 1][prevRow][prevCol] / 8.0;
}
}
}
}
}
// Calculate the final probability: sum of dp[k][r][c] for all cells (r, c) on the board
let result = 0.0;
for (let r = 0; r < n; r++) {
for (let c = 0; c < n; c++) {
result += dp[k][r][c];
}
}
return result;
}
/**
* Calculate the probability that the knight remains on the board after k moves.
* Dynamic Programming with Space Optimization.
*
* @param {number} n - Size of the chessboard
* @param {number} k - Number of moves
* @param {number} row - Starting row
* @param {number} column - Starting column
* @return {number} - Probability that the knight remains on the board
*/
function knightProbabilityOptimized(n, k, row, column) {
// Define the possible knight moves
const directions = [
[-2, -1], [-2, 1], [-1, -2], [-1, 2],
[1, -2], [1, 2], [2, -1], [2, 1]
];
// Initialize arrays for previous and current moves
let prev = Array(n).fill().map(() => Array(n).fill(0.0));
let curr = Array(n).fill().map(() => Array(n).fill(0.0));
// Base case: the knight is at the starting position with 100% probability after 0 moves
prev[row][column] = 1.0;
// Fill arrays
for (let m = 1; m <= k; m++) {
// Reset curr array
curr = Array(n).fill().map(() => Array(n).fill(0.0));
for (let r = 0; r < n; r++) {
for (let c = 0; c < n; c++) {
// For each possible knight move
for (const [dr, dc] of directions) {
// Calculate the previous position
const prevRow = r - dr;
const prevCol = c - dc;
// If the previous position is valid (on the board)
if (prevRow >= 0 && prevRow < n && prevCol >= 0 && prevCol < n) {
// Add the probability of the knight being at the previous position
// divided by 8 (since there are 8 possible moves, each with equal probability)
curr[r][c] += prev[prevRow][prevCol] / 8.0;
}
}
}
}
// Update prev array
prev = curr.map(row => [...row]);
}
// Calculate the final probability: sum of prev[r][c] for all cells (r, c) on the board
let result = 0.0;
for (let r = 0; r < n; r++) {
for (let c = 0; c < n; c++) {
result += prev[r][c];
}
}
return result;
}
/**
* Calculate the probability that the knight remains on the board after k moves.
* Dynamic Programming with further optimization.
*
* @param {number} n - Size of the chessboard
* @param {number} k - Number of moves
* @param {number} row - Starting row
* @param {number} column - Starting column
* @return {number} - Probability that the knight remains on the board
*/
function knightProbabilityMoreOptimized(n, k, row, column) {
// Early return for edge cases
if (k === 0) {
return 1.0;
}
// Define the possible knight moves
const directions = [
[-2, -1], [-2, 1], [-1, -2], [-1, 2],
[1, -2], [1, 2], [2, -1], [2, 1]
];
// Initialize arrays for previous and current moves
let prev = Array(n).fill().map(() => Array(n).fill(0.0));
let curr = Array(n).fill().map(() => Array(n).fill(0.0));
// Base case: the knight is at the starting position with 100% probability after 0 moves
prev[row][column] = 1.0;
// Fill arrays
for (let m = 1; m <= k; m++) {
// Reset curr array
curr = Array(n).fill().map(() => Array(n).fill(0.0));
for (let r = 0; r < n; r++) {
for (let c = 0; c < n; c++) {
if (prev[r][c] === 0.0) {
continue; // Skip cells with zero probability
}
// For each possible knight move
for (const [dr, dc] of directions) {
// Calculate the next position
const nextRow = r + dr;
const nextCol = c + dc;
// If the next position is valid (on the board)
if (nextRow >= 0 && nextRow < n && nextCol >= 0 && nextCol < n) {
// Add the probability of the knight being at the current position
// divided by 8 (since there are 8 possible moves, each with equal probability)
curr[nextRow][nextCol] += prev[r][c] / 8.0;
}
}
}
}
// Update prev array
prev = curr.map(row => [...row]);
}
// Calculate the final probability: sum of prev[r][c] for all cells (r, c) on the board
let result = 0.0;
for (let r = 0; r < n; r++) {
for (let c = 0; c < n; c++) {
result += prev[r][c];
}
}
return result;
}
// Test cases
console.log(knightProbability(3, 2, 0, 0)); // 0.06250
console.log(knightProbability(1, 0, 0, 0)); // 1.00000
console.log(knightProbability(8, 3, 3, 3)); // 0.33594
console.log(knightProbabilityOptimized(3, 2, 0, 0)); // 0.06250
console.log(knightProbabilityOptimized(1, 0, 0, 0)); // 1.00000
console.log(knightProbabilityOptimized(8, 3, 3, 3)); // 0.33594
console.log(knightProbabilityMoreOptimized(3, 2, 0, 0)); // 0.06250
console.log(knightProbabilityMoreOptimized(1, 0, 0, 0)); // 1.00000
console.log(knightProbabilityMoreOptimized(8, 3, 3, 3)); // 0.33594

Step-by-Step Explanation

Let's break down the implementation:

  1. Define Knight Moves: Define the possible knight moves on a chessboard, considering the L-shaped movement pattern of a chess knight.
  2. Initialize DP Array: Set up a dynamic programming array to keep track of the probability of the knight being at each cell after a certain number of moves.
  3. Establish Base Case: Define the base case: the knight is at the starting position with 100% probability after 0 moves.
  4. Fill DP Array: For each move and each cell on the board, calculate the probability of the knight being at that cell by considering all possible previous positions.
  5. Calculate Final Probability: Sum up the probabilities of the knight being at each cell on the board after k moves to get the final probability.
ProblemSolutionCode
101 Logo
onenoughtone