There is an 8 x 8 chessboard containing n pieces (rooks, queens, or bishops). You are given a string array pieces of length n, where pieces[i] describes the type of the ith piece. In addition, you are given a 2D integer array positions also of length n, where positions[i] = [ri, ci] indicates that the ith piece is currently at the 1-based coordinate (ri, ci) on the chessboard.
When making a move for a piece, you choose a destination square that the piece will travel toward and stop on.
A rook can only travel horizontally or vertically from (r, c) to the direction of (r+1, c), (r-1, c), (r, c+1), or (r, c-1).
A queen can only travel horizontally, vertically, or diagonally from (r, c) to the direction of (r+1, c), (r-1, c), (r, c+1), (r, c-1), (r+1, c+1), (r+1, c-1), (r-1, c+1), (r-1, c-1).
A bishop can only travel diagonally from (r, c) to the direction of (r+1, c+1), (r+1, c-1), (r-1, c+1), (r-1, c-1).
You must make a move for every piece on the board simultaneously. A move combination consists of all the moves performed on all the given pieces. Every second, each piece will instantaneously travel one square towards their destination if they are not already at it. All pieces start traveling at the 0th second. A move combination is invalid if, at a given time, two or more pieces occupy the same square.
Return the number of valid move combinations.
Note: No two pieces will start in the same square. You may choose the square a piece is already on as its destination. If two pieces are directly adjacent to each other, it is valid for them to move past each other and swap positions in one second.
Number of Valid Move Combinations On Chessboard — Solution
The key insight is to use backtracking with simulation to check all possible move combinations while pruning invalid paths early. Best approach is optimized backtracking that generates moves piece by piece and detects collisions during path simulation. Time: O(8^n), Space: O(n × max_distance)
For each piece, generate all possible valid destinations based on its type. Then try every combination of moves and simulate the complete movement to check for collisions at any time step.
Optimized Backtracking with Pruning
⏱️ Time: O(8^n) with pruning
Space: O(n × max_distance)
Generate moves for pieces one by one using backtracking. At each step, check if the current partial combination could lead to collisions, and prune impossible branches early to avoid unnecessary computation.
Brute Force with Full Simulation — Algorithm Steps
Generate all possible moves for each piece type
Try every combination of moves
Simulate movement step by step for collision detection
Visualization
Tap to expand
Step-by-Step Walkthrough
1
Generate Moves
List all valid destinations for each piece
2
Try Combinations
Test every combination of moves
3
Simulate
Check for collisions during movement
Code -
solution.c — C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_PIECES 10
#define MAX_MOVES 64
#define MAX_PATH 16
static int allDestinations[MAX_PIECES][MAX_MOVES][2];
static int destCounts[MAX_PIECES];
static int currentMoves[MAX_PIECES][2];
static int positions[MAX_PIECES][2];
static char pieces[MAX_PIECES][10];
static int numPieces;
void getMoves(char* piece, int pos[2], int moves[][2], int* count) {
*count = 0;
moves[(*count)][0] = pos[0];
moves[(*count)][1] = pos[1];
(*count)++;
int r = pos[0], c = pos[1];
int directions[8][2];
int numDirs = 0;
if (strcmp(piece, "rook") == 0) {
directions[0][0] = 0; directions[0][1] = 1;
directions[1][0] = 0; directions[1][1] = -1;
directions[2][0] = 1; directions[2][1] = 0;
directions[3][0] = -1; directions[3][1] = 0;
numDirs = 4;
} else if (strcmp(piece, "bishop") == 0) {
directions[0][0] = 1; directions[0][1] = 1;
directions[1][0] = 1; directions[1][1] = -1;
directions[2][0] = -1; directions[2][1] = 1;
directions[3][0] = -1; directions[3][1] = -1;
numDirs = 4;
} else { // queen
directions[0][0] = 0; directions[0][1] = 1;
directions[1][0] = 0; directions[1][1] = -1;
directions[2][0] = 1; directions[2][1] = 0;
directions[3][0] = -1; directions[3][1] = 0;
directions[4][0] = 1; directions[4][1] = 1;
directions[5][0] = 1; directions[5][1] = -1;
directions[6][0] = -1; directions[6][1] = 1;
directions[7][0] = -1; directions[7][1] = -1;
numDirs = 8;
}
for (int d = 0; d < numDirs; d++) {
int dr = directions[d][0], dc = directions[d][1];
int nr = r + dr, nc = c + dc;
while (nr >= 1 && nr <= 8 && nc >= 1 && nc <= 8) {
moves[*count][0] = nr;
moves[*count][1] = nc;
(*count)++;
nr += dr;
nc += dc;
}
}
}
int getPath(int start[2], int end[2], int path[][2]) {
int pathLen = 0;
if (start[0] == end[0] && start[1] == end[1]) {
path[0][0] = start[0];
path[0][1] = start[1];
return 1;
}
path[pathLen][0] = start[0];
path[pathLen][1] = start[1];
pathLen++;
int r = start[0], c = start[1];
int er = end[0], ec = end[1];
// Calculate direction
int dr = (r == er) ? 0 : ((er > r) ? 1 : -1);
int dc = (c == ec) ? 0 : ((ec > c) ? 1 : -1);
// Generate path
while (r != er || c != ec) {
r += dr;
c += dc;
path[pathLen][0] = r;
path[pathLen][1] = c;
pathLen++;
}
return pathLen;
}
int isValidCombination(int moves[][2], int numMoves) {
static int paths[MAX_PIECES][MAX_PATH][2];
static int pathLens[MAX_PIECES];
int maxSteps = 0;
// Generate paths for all pieces
for (int i = 0; i < numMoves; i++) {
pathLens[i] = getPath(positions[i], moves[i], paths[i]);
maxSteps = (pathLens[i] - 1 > maxSteps) ? pathLens[i] - 1 : maxSteps;
}
// Check for collisions at each time step
for (int t = 0; t <= maxSteps; t++) {
static char occupied[MAX_PIECES * MAX_PATH][10];
int occupiedCount = 0;
for (int i = 0; i < numMoves; i++) {
// Get position at time t
int posIdx = (t < pathLens[i]) ? t : pathLens[i] - 1;
int pos[2] = {paths[i][posIdx][0], paths[i][posIdx][1]};
char posKey[10];
sprintf(posKey, "%d,%d", pos[0], pos[1]);
// Check if already occupied
for (int j = 0; j < occupiedCount; j++) {
if (strcmp(occupied[j], posKey) == 0) {
return 0;
}
}
strcpy(occupied[occupiedCount], posKey);
occupiedCount++;
}
}
return 1;
}
int backtrack(int index) {
if (index == numPieces) {
return isValidCombination(currentMoves, numPieces) ? 1 : 0;
}
int count = 0;
for (int i = 0; i < destCounts[index]; i++) {
currentMoves[index][0] = allDestinations[index][i][0];
currentMoves[index][1] = allDestinations[index][i][1];
count += backtrack(index + 1);
}
return count;
}
int solution() {
// Generate all possible destinations for each piece
for (int i = 0; i < numPieces; i++) {
getMoves(pieces[i], positions[i], allDestinations[i], &destCounts[i]);
}
return backtrack(0);
}
void parsePieces(char* line) {
numPieces = 0;
char* ptr = line + 1; // Skip [
char* start = NULL;
while (*ptr) {
if (*ptr == '"') {
if (start == NULL) {
start = ptr + 1;
} else {
int len = ptr - start;
strncpy(pieces[numPieces], start, len);
pieces[numPieces][len] = '\0';
numPieces++;
start = NULL;
}
}
ptr++;
}
}
void parsePositions(char* line) {
int pieceIdx = 0;
char* ptr = line + 1; // Skip first [
while (*ptr && pieceIdx < numPieces) {
if (*ptr == '[') {
ptr++; // Skip [
char numStr[10];
int numIdx = 0;
int coordIdx = 0;
while (*ptr && *ptr != ']') {
if (*ptr >= '0' && *ptr <= '9') {
numStr[numIdx++] = *ptr;
} else if (*ptr == ',' && numIdx > 0) {
numStr[numIdx] = '\0';
positions[pieceIdx][coordIdx++] = atoi(numStr);
numIdx = 0;
}
ptr++;
}
if (numIdx > 0) {
numStr[numIdx] = '\0';
positions[pieceIdx][coordIdx] = atoi(numStr);
}
pieceIdx++;
}
ptr++;
}
}
int main() {
char line1[1000], line2[1000];
fgets(line1, sizeof(line1), stdin);
fgets(line2, sizeof(line2), stdin);
// Remove newlines
line1[strcspn(line1, "\n")] = 0;
line2[strcspn(line2, "\n")] = 0;
parsePieces(line1);
parsePositions(line2);
printf("%d\n", solution());
return 0;
}
Time & Space Complexity
Time Complexity
⏱️
O(8^n × max_distance)
Each piece has up to 8 directions with multiple distances, creating exponential combinations
n
2n
✓ Linear Growth
Space Complexity
O(n × max_distance)
Store all possible moves and simulation states
n
2n
⚡ Linearithmic Space
15.4K Views
MediumFrequency
~35 minAvg. Time
267 Likes
Ln 1, Col 1
Smart Actions
💡Explanation
AI Ready
💡 SuggestionTabto acceptEscto dismiss
// Output will appear here after running code
Code Editor Closed
Click the red button to reopen
Algorithm Visualization
Pinch to zoom • Tap outside to close
Test Cases
0 passed
0 failed
3 pending
Select Compiler
Choose a programming language
Compiler list would appear here...
AI Editor Features
Header Buttons
💡
Explain
Get a detailed explanation of your code. Select specific code or analyze the entire file. Understand algorithms, logic flow, and complexity.
🔧
Fix
Automatically detect and fix issues in your code. Finds bugs, syntax errors, and common mistakes. Shows you what was fixed.
💡
Suggest
Get improvement suggestions for your code. Best practices, performance tips, and code quality recommendations.
💬
Ask AI
Open an AI chat assistant to ask any coding questions. Have a conversation about your code, get help with debugging, or learn new concepts.
Smart Actions (Slash Commands)
🔧
/fix Enter
Find and fix issues in your code. Detects common problems and applies automatic fixes.
💡
/explain Enter
Get a detailed explanation of what your code does, including time/space complexity analysis.
🧪
/tests Enter
Automatically generate unit tests for your code. Creates comprehensive test cases.
📝
/docs Enter
Generate documentation for your code. Creates docstrings, JSDoc comments, and type hints.
⚡
/optimize Enter
Get performance optimization suggestions. Improve speed and reduce memory usage.
AI Code Completion (Copilot-style)
👻
Ghost Text Suggestions
As you type, AI suggests code completions shown in gray text. Works with keywords like def, for, if, etc.
Tabto acceptEscto dismiss
💬
Comment-to-Code
Write a comment describing what you want, and AI generates the code. Try: # two sum, # binary search, # fibonacci
💡
Pro Tip: Select specific code before using Explain, Fix, or Smart Actions to analyze only that portion. Otherwise, the entire file will be analyzed.