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

6.9 KiB
Raw Blame History

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:

./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)

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:

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:

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! 🚀