EX_03/n_queens/README.md
2025-09-22 17:08:03 +01:00

252 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# N-Queens Problem - Simple Explanation 👑
## What is the N-Queens Problem? 🤔
Imagine you have a chessboard and some queens (the most powerful pieces in chess). The N-Queens problem is like a puzzle where you need to place N queens on an N×N chessboard so that **none of them can attack each other**.
### What's a Queen in Chess? ♛
A queen is the strongest piece in chess. She can move:
- **Horizontally** (left and right) ←→
- **Vertically** (up and down) ↕️
- **Diagonally** (in any diagonal direction) ↗️↖️↙️↘️
She can move as many squares as she wants in these directions!
## The Challenge 🎯
Let's say we want to solve the **4-Queens problem** (N=4):
- We have a 4×4 chessboard (16 squares total)
- We need to place 4 queens
- **NO queen can attack any other queen**
### Example: What Does "Attack" Mean?
If we put a queen at position (0,0) - that's the top-left corner - she can attack:
```
Q . . . ← Queen here attacks all positions marked with X
X . . .
X . . .
X . . .
```
```
Q X X X ← Queen attacks horizontally
. . . .
. . . .
. . . .
```
```
Q . . . ← Queen attacks diagonally
. X . .
. . X .
. . . X
```
So we can't put any other queen in any of those X positions!
## How Our Program Works 🖥️
### Step 1: Understanding the Input
When you run our program like this:
```bash
./n_queens 4
```
The number `4` means "solve the 4-Queens problem" (4×4 board with 4 queens).
### Step 2: How We Represent the Solution
Instead of drawing the whole board, we use a clever trick! Since we know:
- There must be exactly ONE queen in each row
- There must be exactly ONE queen in each column
We can represent a solution as a list of numbers:
```
1 3 0 2
```
This means:
- **Row 0**: Queen is in column 1
- **Row 1**: Queen is in column 3
- **Row 2**: Queen is in column 0
- **Row 3**: Queen is in column 2
### Step 3: Visualizing the Solution
If we draw this on a 4×4 board:
```
. Q . . ← Row 0, Column 1
. . . Q ← Row 1, Column 3
Q . . . ← Row 2, Column 0
. . Q . ← Row 3, Column 2
```
Let's check: Can any queen attack another?
- Queen at (0,1): Can't attack any other queen ✅
- Queen at (1,3): Can't attack any other queen ✅
- Queen at (2,0): Can't attack any other queen ✅
- Queen at (3,2): Can't attack any other queen ✅
Perfect! This is a valid solution!
## How Our Code Works 🔧
### The Main Function (`main`)
```c
int main(int argc, char **argv)
{
int n;
int *queens;
if (argc != 2) // Check if user gave us exactly one number
return (1);
n = atoi(argv[1]); // Convert the text "4" to number 4
if (n <= 0) // Make sure the number is positive
return (1);
queens = (int *)malloc(sizeof(int) * n); // Create space to store queen positions
if (!queens) // Check if we got the memory
return (1);
solve_nqueens(queens, 0, n); // Start solving from row 0
free(queens); // Clean up memory
return (0);
}
```
**What this does in simple terms:**
1. "Did the user give me a number?"
2. "Is it a good number (positive)?"
3. "Let me create space to remember where I put the queens"
4. "Now let me solve the puzzle!"
5. "Clean up when I'm done"
### The Solver Function (`solve_nqueens`)
This is the "brain" of our program. It uses a technique called **backtracking**:
```c
void solve_nqueens(int *queens, int row, int n)
{
int col;
if (row == n) // Did I place all queens?
{
print_solution(queens, n); // Yes! Print this solution
return ;
}
col = 0;
while (col < n) // Try each column in this row
{
if (is_safe(queens, row, col, n)) // Can I put a queen here?
{
queens[row] = col; // Yes! Put the queen here
solve_nqueens(queens, row + 1, n); // Try the next row
}
col++;
}
}
```
**Think of it like this:**
1. "Am I done placing all queens?" → If yes, print the solution!
2. "If not, let me try putting a queen in each column of this row"
3. "For each column, ask: Is it safe to put a queen here?"
4. "If safe, put the queen there and try to solve the next row"
### The Safety Check (`is_safe`)
This function checks if a queen position is safe:
```c
int is_safe(int *queens, int row, int col, int n)
{
int i;
i = 0;
while (i < row) // Check all previously placed queens
{
if (queens[i] == col) // Same column?
return (0); // Not safe!
if (queens[i] - i == col - row) // Same diagonal (\)?
return (0); // Not safe!
if (queens[i] + i == col + row) // Same diagonal (/)?
return (0); // Not safe!
i++;
}
return (1); // Safe to place queen here!
}
```
**The three checks:**
1. **Same column**: `queens[i] == col`
- "Is there already a queen in this column?"
2. **Diagonal 1**: `queens[i] - i == col - row`
- "Is there a queen on the same diagonal going from top-left to bottom-right?"
3. **Diagonal 2**: `queens[i] + i == col + row`
- "Is there a queen on the same diagonal going from top-right to bottom-left?"
## Example Run 🏃‍♂️
Let's trace through what happens when we run `./n_queens 4`:
1. **Start with row 0**: Try putting a queen in each column
- Column 0: Check safety → Safe! Put queen at (0,0)
- Move to row 1
2. **Row 1**: Try each column
- Column 0: Not safe (same column as row 0)
- Column 1: Not safe (same column... wait, no queen there yet)
- Column 2: Check safety → Safe! Put queen at (1,2)
- Move to row 2
3. **Row 2**: Try each column
- Column 0: Not safe (diagonal conflict)
- Column 1: Not safe (diagonal conflict)
- Column 2: Not safe (same column as row 1)
- Column 3: Not safe (diagonal conflict)
- **No solution found!** Go back to row 1
4. **Back to row 1**: Try next column
- Column 3: Check safety → Safe! Put queen at (1,3)
- Move to row 2
5. Continue this process...
Eventually, we find: `1 3 0 2` and `2 0 3 1`
## Results for Different N Values 📊
- **N=1**: `0` (1 solution - just put the queen anywhere)
- **N=2**: No output (impossible to solve)
- **N=3**: No output (impossible to solve)
- **N=4**: `1 3 0 2` and `2 0 3 1` (2 solutions)
- **N=8**: 92 solutions!
## Fun Facts! 🎉
1. **Why no solution for N=2 and N=3?**
- For N=2: You need 2 queens on a 2×2 board, but they'll always attack each other!
- For N=3: Same problem - not enough space!
2. **The 8-Queens problem** (standard chessboard) has exactly **92 solutions**!
3. **This is a classic computer science problem** that teaches us about:
- **Recursion** (functions calling themselves)
- **Backtracking** (trying something, and if it doesn't work, going back and trying something else)
- **Problem solving** (breaking a big problem into smaller pieces)
## How to Use the Program 💻
1. **Compile**: `make`
2. **Run**: `./n_queens 4`
3. **Test different values**: `make test`
4. **Clean up**: `make clean`
Try it with different numbers and see what happens! 🚀