added n_queens
This commit is contained in:
parent
f755b9a481
commit
36a3a5a8aa
86
n_queens/Makefile
Normal file
86
n_queens/Makefile
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
# **************************************************************************** #
|
||||||
|
# #
|
||||||
|
# ::: :::::::: #
|
||||||
|
# Makefile :+: :+: :+: #
|
||||||
|
# +:+ +:+ +:+ #
|
||||||
|
# By: ruiferna <ruiferna@student.42porto.com> +#+ +:+ +#+ #
|
||||||
|
# +#+#+#+#+#+ +#+ #
|
||||||
|
# Created: 2025/09/22 17:06:00 by ruiferna #+# #+# #
|
||||||
|
# Updated: 2025/09/22 17:07:38 by ruiferna ### ########.fr #
|
||||||
|
# #
|
||||||
|
# **************************************************************************** #
|
||||||
|
|
||||||
|
# Program name
|
||||||
|
NAME = n_queens
|
||||||
|
|
||||||
|
# Compiler and flags
|
||||||
|
CC = gcc
|
||||||
|
CFLAGS = -Wall -Wextra -Werror
|
||||||
|
|
||||||
|
# Source files
|
||||||
|
SRCS = n_queens.c
|
||||||
|
|
||||||
|
# Object files
|
||||||
|
OBJS = $(SRCS:.c=.o)
|
||||||
|
|
||||||
|
# Header files
|
||||||
|
HEADERS = n_queens.h
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
GREEN = \033[0;32m
|
||||||
|
RED = \033[0;31m
|
||||||
|
RESET = \033[0m
|
||||||
|
|
||||||
|
# Main rule
|
||||||
|
all: $(NAME)
|
||||||
|
|
||||||
|
# Compile the program
|
||||||
|
$(NAME): $(OBJS)
|
||||||
|
@echo "$(GREEN)Compiling $(NAME)...$(RESET)"
|
||||||
|
@$(CC) $(CFLAGS) $(OBJS) -o $(NAME)
|
||||||
|
@echo "$(GREEN)✓ $(NAME) compiled successfully!$(RESET)"
|
||||||
|
|
||||||
|
# Compile object files
|
||||||
|
%.o: %.c $(HEADERS)
|
||||||
|
@echo "Compiling $<..."
|
||||||
|
@$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
# Clean object files
|
||||||
|
clean:
|
||||||
|
@echo "$(RED)Cleaning object files...$(RESET)"
|
||||||
|
@rm -f $(OBJS)
|
||||||
|
@echo "$(RED)✓ Object files cleaned!$(RESET)"
|
||||||
|
|
||||||
|
# Clean everything
|
||||||
|
fclean: clean
|
||||||
|
@echo "$(RED)Cleaning executable...$(RESET)"
|
||||||
|
@rm -f $(NAME)
|
||||||
|
@echo "$(RED)✓ Everything cleaned!$(RESET)"
|
||||||
|
|
||||||
|
# Rebuild everything
|
||||||
|
re: fclean all
|
||||||
|
|
||||||
|
# Test the program with different values
|
||||||
|
test: $(NAME)
|
||||||
|
@echo "$(GREEN)Testing n_queens program:$(RESET)"
|
||||||
|
@echo "\n$(GREEN)Testing with n=1:$(RESET)"
|
||||||
|
@./$(NAME) 1
|
||||||
|
@echo "\n$(GREEN)Testing with n=2 (no solutions):$(RESET)"
|
||||||
|
@./$(NAME) 2 || echo "No solutions found"
|
||||||
|
@echo "\n$(GREEN)Testing with n=4:$(RESET)"
|
||||||
|
@./$(NAME) 4
|
||||||
|
@echo "\n$(GREEN)Testing with n=8 (counting solutions):$(RESET)"
|
||||||
|
@echo "Number of solutions for n=8: $$(./$(NAME) 8 | wc -l)"
|
||||||
|
|
||||||
|
# Display help
|
||||||
|
help:
|
||||||
|
@echo "$(GREEN)Available commands:$(RESET)"
|
||||||
|
@echo " make - Compile the program"
|
||||||
|
@echo " make clean - Remove object files"
|
||||||
|
@echo " make fclean - Remove all generated files"
|
||||||
|
@echo " make re - Rebuild everything"
|
||||||
|
@echo " make test - Run tests with different values"
|
||||||
|
@echo " make help - Show this help message"
|
||||||
|
|
||||||
|
# Declare phony targets
|
||||||
|
.PHONY: all clean fclean re test help
|
||||||
252
n_queens/README.md
Normal file
252
n_queens/README.md
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
# 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! 🚀
|
||||||
96
n_queens/n_queens.c
Normal file
96
n_queens/n_queens.c
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* ::: :::::::: */
|
||||||
|
/* n_queens.c :+: :+: :+: */
|
||||||
|
/* +:+ +:+ +:+ */
|
||||||
|
/* By: ruiferna <ruiferna@student.42porto.com> +#+ +:+ +#+ */
|
||||||
|
/* +#+#+#+#+#+ +#+ */
|
||||||
|
/* Created: 2025/09/22 00:00:00 by student #+# #+# */
|
||||||
|
/* Updated: 2025/09/22 17:05:44 by ruiferna ### ########.fr */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
#include "n_queens.h"
|
||||||
|
|
||||||
|
void print_number(int n)
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
|
||||||
|
if (n >= 10)
|
||||||
|
print_number(n / 10);
|
||||||
|
c = '0' + (n % 10);
|
||||||
|
write(1, &c, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_solution(int *queens, int n)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while (i < n)
|
||||||
|
{
|
||||||
|
if (i > 0)
|
||||||
|
write(1, " ", 1);
|
||||||
|
print_number(queens[i]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
write(1, "\n", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int is_safe(int *queens, int row, int col, int n)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
(void)n;
|
||||||
|
i = 0;
|
||||||
|
while (i < row)
|
||||||
|
{
|
||||||
|
if (queens[i] == col)
|
||||||
|
return (0);
|
||||||
|
if (queens[i] - i == col - row)
|
||||||
|
return (0);
|
||||||
|
if (queens[i] + i == col + row)
|
||||||
|
return (0);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void solve_nqueens(int *queens, int row, int n)
|
||||||
|
{
|
||||||
|
int col;
|
||||||
|
|
||||||
|
if (row == n)
|
||||||
|
{
|
||||||
|
print_solution(queens, n);
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
col = 0;
|
||||||
|
while (col < n)
|
||||||
|
{
|
||||||
|
if (is_safe(queens, row, col, n))
|
||||||
|
{
|
||||||
|
queens[row] = col;
|
||||||
|
solve_nqueens(queens, row + 1, n);
|
||||||
|
}
|
||||||
|
col++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
int *queens;
|
||||||
|
|
||||||
|
if (argc != 2)
|
||||||
|
return (1);
|
||||||
|
n = atoi(argv[1]);
|
||||||
|
if (n <= 0)
|
||||||
|
return (1);
|
||||||
|
queens = (int *)malloc(sizeof(int) * n);
|
||||||
|
if (!queens)
|
||||||
|
return (1);
|
||||||
|
solve_nqueens(queens, 0, n);
|
||||||
|
free(queens);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
25
n_queens/n_queens.h
Normal file
25
n_queens/n_queens.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* ::: :::::::: */
|
||||||
|
/* n_queens.h :+: :+: :+: */
|
||||||
|
/* +:+ +:+ +:+ */
|
||||||
|
/* By: ruiferna <ruiferna@student.42porto.com> +#+ +:+ +#+ */
|
||||||
|
/* +#+#+#+#+#+ +#+ */
|
||||||
|
/* Created: 2025/09/22 00:00:00 by student #+# #+# */
|
||||||
|
/* Updated: 2025/09/22 17:05:44 by ruiferna ### ########.fr */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
#ifndef N_QUEENS_H
|
||||||
|
# define N_QUEENS_H
|
||||||
|
|
||||||
|
# include <stdlib.h>
|
||||||
|
# include <unistd.h>
|
||||||
|
# include <stdio.h>
|
||||||
|
|
||||||
|
int is_safe(int *queens, int row, int col, int n);
|
||||||
|
void solve_nqueens(int *queens, int row, int n);
|
||||||
|
void print_solution(int *queens, int n);
|
||||||
|
void print_number(int n);
|
||||||
|
|
||||||
|
#endif
|
||||||
28
n_queens/subject.txt
Normal file
28
n_queens/subject.txt
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
Assignement name : n_queens
|
||||||
|
|
||||||
|
Expected files : *.c *.h
|
||||||
|
|
||||||
|
Allowed functions : atoi, fprintf, write, calloc, malloc, free, realloc, stdout, stderr
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Write a program that will print all the solutions to the n queens problem
|
||||||
|
for a n given as argument.
|
||||||
|
We will not test with negative values.
|
||||||
|
The order of the solutions is not important.
|
||||||
|
|
||||||
|
You will display the solutions under the following format :
|
||||||
|
<p1> <p2> <p3> ... \n
|
||||||
|
where pn are the line index of the queen in each colum starting from 0.
|
||||||
|
|
||||||
|
For example this should work :
|
||||||
|
$> ./n_queens 2 | cat -e
|
||||||
|
|
||||||
|
$> ./n_queens 4 | cat -e
|
||||||
|
1 3 0 2$
|
||||||
|
2 0 3 1$
|
||||||
|
|
||||||
|
$> ./n_queens 7 | cat -e
|
||||||
|
0 2 4 6 1 3 5$
|
||||||
|
0 3 6 2 5 1 4$
|
||||||
|
etc...
|
||||||
Loading…
Reference in New Issue
Block a user