removed dups

This commit is contained in:
Rui Ribeiro 2025-09-23 08:43:55 +01:00
parent 259d4ef6f3
commit 0ec1385e07
25 changed files with 0 additions and 2103 deletions

View File

@ -1,74 +0,0 @@
# 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

View File

@ -1,252 +0,0 @@
# 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! 🚀

View File

@ -1,84 +0,0 @@
#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);
}

View File

@ -1,13 +0,0 @@
#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

View File

@ -1,28 +0,0 @@
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...

View File

@ -1,25 +0,0 @@
NAME = permutations
CC = gcc
CFLAGS = -Wall -Wextra -Werror
SRCS = permutations.c
OBJS = $(SRCS:.c=.o)
all: $(NAME)
$(NAME): $(OBJS)
$(CC) $(CFLAGS) -o $(NAME) $(OBJS)
%.o: %.c permutations.h
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -f $(OBJS)
fclean: clean
rm -f $(NAME)
re: fclean all
.PHONY: all clean fclean re

View File

@ -1,200 +0,0 @@
# Permutations Exercise - Simple Explanation 🔄
## What is a Permutation? 🤔
Imagine you have some letters, like the letters in your name. A **permutation** is just a fancy word for "all the different ways you can arrange those letters."
Think of it like this:
- If you have the letters **A** and **B**, you can arrange them as **AB** or **BA**
- If you have **A**, **B**, and **C**, you can make **ABC**, **ACB**, **BAC**, **BCA**, **CAB**, **CBA**
It's like having alphabet blocks and seeing how many different words you can spell by changing the order!
## The Challenge 🎯
Your mission is to write a program that:
1. Takes a word (like "abc")
2. Shows ALL possible ways to rearrange the letters
3. Shows them in **alphabetical order** (like in a dictionary)
## Real Examples 📝
Let's see what our program does:
### Example 1: Single Letter
```bash
./permutations a
```
**Output:** `a`
*Why?* There's only one letter, so there's only one way to arrange it!
### Example 2: Two Letters
```bash
./permutations ab
```
**Output:**
```
ab
ba
```
*Why?* We can put 'a' first or 'b' first. That's it!
### Example 3: Three Letters
```bash
./permutations abc
```
**Output:**
```
abc
acb
bac
bca
cab
cba
```
*Why?* Think of it step by step:
- Start with 'a': we can make **abc** and **acb**
- Start with 'b': we can make **bac** and **bca**
- Start with 'c': we can make **cab** and **cba**
## How Our Code Works 🛠️
### Step 1: Getting Ready
```c
// We take the word you give us
char *str = argv[1]; // This is your word like "abc"
// We make a copy so we don't mess up the original
copy = malloc(sizeof(char) * (len + 1));
```
### Step 2: Sorting First (The Secret Sauce! ✨)
```c
ft_sort_string(copy); // This puts letters in order: "cba" becomes "abc"
```
**Why do we sort first?**
- If someone gives us "cba", we sort it to "abc" first
- This way, we always start with letters in alphabetical order
- Then when we make all arrangements, they come out in the right order!
### Step 3: The Magic Swapping Function
```c
void ft_swap(char *a, char *b)
{
char temp = *a; // Remember the first letter
*a = *b; // Put the second letter in first position
*b = temp; // Put the first letter in second position
}
```
**What's swapping?** It's like switching two cards in your hand:
- You have cards **A** and **B**
- After swapping, you have **B** and **A**
### Step 4: The Next Permutation Magic 🪄
```c
int next_permutation(char *str, int len)
{
int i = len - 2;
while (i >= 0 && str[i] >= str[i + 1]) // Find rightmost character smaller than next
i--;
if (i < 0)
return (0); // No more permutations
int j = len - 1;
while (str[j] <= str[i]) // Find rightmost character greater than str[i]
j--;
ft_swap(&str[i], &str[j]); // Swap them
ft_reverse(str, i + 1, len - 1); // Reverse the suffix
return (1); // Successfully generated next permutation
}
```
**How does this work?** Think of it like counting in a special way:
1. **Find** the rightmost place where we can "increment" (make it bigger)
2. **Swap** with the next bigger character available
3. **Reverse** everything after that position to get the smallest arrangement
4. **Repeat** until no more permutations exist
It's like a smart odometer that counts through all possible letter arrangements in perfect alphabetical order!
### Step 5: The Main Loop 🔄
```c
ft_sort_string(copy); // Start with alphabetically first arrangement
puts(copy); // Print the first permutation
while (next_permutation(copy, len)) // While there are more permutations
puts(copy); // Print each one
```
**How does this work?**
1. **Start** with the smallest (first) arrangement: "abc"
2. **Print** it
3. **Generate** the next alphabetical arrangement using `next_permutation`
4. **Print** it
5. **Repeat** until `next_permutation` says "no more!"
It's like flipping through a dictionary - each page (permutation) comes in perfect alphabetical order!
## Why This Approach is Cool 😎
### The Step-by-Step Process 📋
When we have "abc", our program works like this:
```
1. Start: abc (sorted, print it!)
2. Next: acb (swap 'b' and 'c', print it!)
3. Next: bac (find next in alphabetical order, print it!)
4. Next: bca (continue the pattern, print it!)
5. Next: cab (keep going, print it!)
6. Next: cba (last one, print it!)
7. Done: No more permutations possible
```
**The Magic:** Each step finds the next arrangement that would come after the current one in a dictionary! It's like having a super-smart assistant who knows exactly what comes next alphabetically.
### Memory Management 🧠
```c
copy = malloc(sizeof(char) * (len + 1)); // Ask for memory
// ... do our work ...
free(copy); // Give memory back when done
```
We're polite programmers - we clean up after ourselves!
### Error Handling 🛡️
```c
if (argc != 2) // Did you give us exactly one word?
return (1); // If not, we quit
if (!copy) // Did we get the memory we asked for?
return (1); // If not, we quit safely
```
We check if things went wrong and handle it gracefully.
## Fun Facts! 🎉
- With 1 letter: **1** permutation
- With 2 letters: **2** permutations
- With 3 letters: **6** permutations
- With 4 letters: **24** permutations
- With 5 letters: **120** permutations
**Pattern?** For n letters, you get n × (n-1) × (n-2) × ... × 1 permutations!
## Try It Yourself! 🚀
1. Compile the program: `gcc -Wall -Wextra -Werror permutations.c -o permutations`
2. Try it with your name: `./permutations john`
3. Try it with short words: `./permutations cat`
4. See how the results are always in alphabetical order!
Remember: The computer is doing exactly what we told it to do, step by step, just like following a recipe! 👨‍🍳
---
*Made with ❤️ for curious minds who want to understand how permutations work!*

View File

@ -1,98 +0,0 @@
#include "permutations.h"
int ft_strlen(char *str)
{
int len;
len = 0;
while (str[len])
len++;
return (len);
}
void ft_swap(char *a, char *b)
{
char temp;
temp = *a;
*a = *b;
*b = temp;
}
void ft_sort_string(char *str)
{
int i;
int j;
int len;
len = ft_strlen(str);
i = 0;
while (i < len - 1)
{
j = i + 1;
while (j < len)
{
if (str[i] > str[j])
ft_swap(&str[i], &str[j]);
j++;
}
i++;
}
}
void ft_reverse(char *str, int start, int end)
{
while (start < end)
{
ft_swap(&str[start], &str[end]);
start++;
end--;
}
}
int next_permutation(char *str, int len)
{
int i;
int j;
i = len - 2;
while (i >= 0 && str[i] >= str[i + 1])
i--;
if (i < 0)
return (0);
j = len - 1;
while (str[j] <= str[i])
j--;
ft_swap(&str[i], &str[j]);
ft_reverse(str, i + 1, len - 1);
return (1);
}
int main(int argc, char **argv)
{
char *str;
char *copy;
int len;
int i;
if (argc != 2)
return (1);
str = argv[1];
len = ft_strlen(str);
copy = malloc(sizeof(char) * (len + 1));
if (!copy)
return (1);
i = 0;
while (i < len)
{
copy[i] = str[i];
i++;
}
copy[len] = '\0';
ft_sort_string(copy);
puts(copy);
while (next_permutation(copy, len))
puts(copy);
free(copy);
return (0);
}

View File

@ -1,14 +0,0 @@
#ifndef PERMUTATIONS_H
# define PERMUTATIONS_H
# include <stdlib.h>
# include <unistd.h>
# include <stdio.h>
void ft_swap(char *a, char *b);
void ft_sort_string(char *str);
void ft_reverse(char *str, int start, int end);
int next_permutation(char *str, int len);
int ft_strlen(char *str);
#endif

View File

@ -1,27 +0,0 @@
Assignment name : permutations
Expected files : *.c *.h
Allowed functions: puts, malloc, calloc, realloc, free, write
---------------------------------------------------------------
Write a program that will print all the permutations of a string given as argument.
The solutions must be given in alphabetical order.
We will not try your program with strings containing duplicates (eg: 'abccd').
For example this should work:
$> ./permutations a | cat -e
a$
$> ./permutations ab | cat -e
ab$
ba$
$> ./permutations abc | cat -e
abc$
acb$
bac$
bca$
cab$
cba$

View File

@ -1,71 +0,0 @@
# Program name
NAME = powerset
# Compiler and flags
CC = gcc
CFLAGS = -Wall -Wextra -Werror
# Source files
SRCS = powerset.c
OBJS = $(SRCS:.c=.o)
# Header files
HEADERS = powerset.h
# Colors for output
GREEN = \033[0;32m
RED = \033[0;31m
RESET = \033[0m
# Default target
all: $(NAME)
# Build the program
$(NAME): $(OBJS)
@echo "$(GREEN)Linking $(NAME)...$(RESET)"
@$(CC) $(CFLAGS) $(OBJS) -o $(NAME)
@echo "$(GREEN)$(NAME) compiled successfully!$(RESET)"
# Compile source files to object files
%.o: %.c $(HEADERS)
@echo "$(GREEN)Compiling $<...$(RESET)"
@$(CC) $(CFLAGS) -c $< -o $@
# Clean object files
clean:
@echo "$(RED)Cleaning object files...$(RESET)"
@rm -f $(OBJS)
# Clean everything
fclean: clean
@echo "$(RED)Cleaning $(NAME)...$(RESET)"
@rm -f $(NAME)
# Rebuild everything
re: fclean all
# Test the program with the examples from the subject
test: $(NAME)
@echo "$(GREEN)Running tests...$(RESET)"
@echo "\n$(GREEN)Test 1: powerset 3 1 0 2 4 5 3$(RESET)"
@./$(NAME) 3 1 0 2 4 5 3
@echo "\n$(GREEN)Test 2: powerset 12 5 2 1 8 4 3 7 11$(RESET)"
@./$(NAME) 12 5 2 1 8 4 3 7 11
@echo "\n$(GREEN)Test 3: powerset 0 1 -1$(RESET)"
@./$(NAME) 0 1 -1
@echo "\n$(GREEN)Test 4: powerset 7 3 8 2 (should be empty)$(RESET)"
@./$(NAME) 7 3 8 2
@echo "$(GREEN)✓ All tests completed!$(RESET)"
# Help
help:
@echo "Available targets:"
@echo " all - Build the program (default)"
@echo " clean - Remove object files"
@echo " fclean - Remove object files and executable"
@echo " re - Rebuild everything"
@echo " test - Run test cases"
@echo " help - Show this help message"
# Declare phony targets
.PHONY: all clean fclean re test help

View File

@ -1,175 +0,0 @@
# Powerset Exercise - Simple Explanation 🧮
## What is this exercise about?
Imagine you have a bag of numbered balls, and you want to find all the different ways you can pick some balls so that the numbers on them add up to a specific target number.
This is exactly what the **powerset** exercise does!
## Real-world example 🎯
Let's say you have these numbered balls: **1, 2, 3, 4, 5**
And you want to find all the ways to pick balls that add up to **5**.
Here are all the possible ways:
- Pick just ball **5** → 5 = 5 ✅
- Pick balls **1** and **4** → 1 + 4 = 5 ✅
- Pick balls **2** and **3** → 2 + 3 = 5 ✅
So the answer would be:
```
5
1 4
2 3
```
## How does our program work? 🤖
### Step 1: Understanding the input
When you run the program like this:
```bash
./powerset 5 1 2 3 4 5
```
- **5** is our target number (what we want the balls to add up to)
- **1 2 3 4 5** are our numbered balls
### Step 2: The magic behind the scenes
Our program is like a smart robot that tries **every possible combination**:
1. **Try no balls at all** → sum = 0 (not 5, so skip)
2. **Try just ball 1** → sum = 1 (not 5, so skip)
3. **Try just ball 2** → sum = 2 (not 5, so skip)
4. **Try just ball 3** → sum = 3 (not 5, so skip)
5. **Try just ball 4** → sum = 4 (not 5, so skip)
6. **Try just ball 5** → sum = 5 ✅ **FOUND ONE!**
7. **Try balls 1 and 2** → sum = 3 (not 5, so skip)
8. **Try balls 1 and 3** → sum = 4 (not 5, so skip)
9. **Try balls 1 and 4** → sum = 5 ✅ **FOUND ANOTHER!**
10. **Try balls 2 and 3** → sum = 5 ✅ **FOUND ANOTHER!**
...and so on until it tries every possible combination!
## Code explanation 📝
### The main parts of our code:
#### 1. Reading the input (`main` function)
```c
target = atoi(argv[1]); // Get the target number (5 in our example)
set[i] = atoi(argv[i + 2]); // Get each ball number (1, 2, 3, 4, 5)
```
#### 2. The smart robot (`find_subsets` function)
This function is like our robot that tries every combination:
```c
// For each ball, we have 2 choices:
find_subsets(..., index + 1); // Don't pick this ball
subset[subset_size] = set[index]; // Pick this ball
find_subsets(..., subset_size + 1, ...); // Continue with this ball included
```
#### 3. Checking if we found a winner (`print_subset`)
```c
if (current_sum == target) // If the sum equals our target
print_subset(subset, subset_size); // Show this combination!
```
## More examples to understand better 🎲
### Example 1: Finding combinations that sum to 3
```bash
./powerset 3 1 0 2 4 5 3
```
**What the robot finds:**
- Ball **3** alone → 3 ✅
- Balls **0** and **3** → 0 + 3 = 3 ✅
- Balls **1** and **2** → 1 + 2 = 3 ✅
- Balls **1**, **0**, and **2** → 1 + 0 + 2 = 3 ✅
**Output:**
```
3
0 3
1 2
1 0 2
```
### Example 2: Finding the empty combination
```bash
./powerset 0 1 -1
```
**What the robot finds:**
- No balls picked → sum = 0 ✅ (shows as empty line)
- Balls **1** and **-1** → 1 + (-1) = 0 ✅
**Output:**
```
1 -1
```
(Notice the empty line at the top!)
### Example 3: When nothing works
```bash
./powerset 7 3 8 2
```
**What the robot finds:**
- No combination of 3, 8, and 2 can make 7
- So nothing gets printed (empty output)
## Important rules 📏
1. **Order matters**: We always keep balls in the same order as given
- ✅ Correct: `1 4` (1 comes before 4 in input)
- ❌ Wrong: `4 1` (this changes the order)
2. **No duplicates**: Each ball can only be used once per combination
3. **Empty combination counts**: If target is 0, picking no balls is valid!
## How to use the program 🚀
1. **Compile it:**
```bash
make
```
2. **Run tests:**
```bash
make test
```
3. **Try your own examples:**
```bash
./powerset [target_number] [ball1] [ball2] [ball3] ...
```
4. **Clean up:**
```bash
make clean # Remove temporary files
make fclean # Remove everything
```
## Fun challenge! 🎮
Try to predict what this will output before running it:
```bash
./powerset 6 1 2 3 4
```
**Think about it:**
- Which combinations of 1, 2, 3, 4 add up to 6?
- Remember: order matters and each number can only be used once!
**Answer:** `2 4` and `1 2 3` (because 2+4=6 and 1+2+3=6)
---
*Now you understand how the powerset exercise works! It's like having a super-smart robot that can instantly try every possible combination of numbers to find the ones that add up to your target. Pretty cool, right?* 🤖✨

View File

@ -1,73 +0,0 @@
#include "powerset.h"
void print_subset(int *subset, int size)
{
int i;
i = 0;
while (i < size)
{
printf("%d", subset[i]);
if (i < size - 1)
printf(" ");
i++;
}
printf("\n");
}
void find_subsets(int *set, int set_size, int target, int *subset,
int subset_size, int index)
{
int current_sum;
int i;
if (index == set_size)
{
current_sum = 0;
i = 0;
while (i < subset_size)
{
current_sum += subset[i];
i++;
}
if (current_sum == target)
print_subset(subset, subset_size);
return ;
}
find_subsets(set, set_size, target, subset, subset_size, index + 1);
subset[subset_size] = set[index];
find_subsets(set, set_size, target, subset, subset_size + 1, index + 1);
}
int main(int argc, char **argv)
{
int *set;
int *subset;
int target;
int set_size;
int i;
if (argc < 2)
return (1);
target = atoi(argv[1]);
set_size = argc - 2;
set = malloc(sizeof(int) * set_size);
if (!set)
return (1);
subset = malloc(sizeof(int) * set_size);
if (!subset)
{
free(set);
return (1);
}
i = 0;
while (i < set_size)
{
set[i] = atoi(argv[i + 2]);
i++;
}
find_subsets(set, set_size, target, subset, 0, 0);
free(set);
free(subset);
return (0);
}

View File

@ -1,12 +0,0 @@
#ifndef POWERSET_H
# define POWERSET_H
# include <stdlib.h>
# include <unistd.h>
# include <stdio.h>
void find_subsets(int *set, int set_size, int target, int *subset,
int subset_size, int index);
void print_subset(int *subset, int size);
#endif

View File

@ -1,65 +0,0 @@
Assignment name : powerset
Expected files : *.c *.h
Allowed functions: atoi, printf, fprintf, malloc, calloc, realloc, free, stdout,
write
--------------------------------------------------------------------------------
Write a program that will take as argument an integer n followed by a set s of
distinct integers.
Your program should display all the subsets of s whose sum of elements is n.
The order of the lines is not important, but the order of the elements in a subset is:
it must match the order in the initial set s.
This way, you should not have any duplicates (eg: '1 2' and '2 1').
For example, using the command ./powerset 5 1 2 3 4 5
this output is valid:
1 4
2 3
5
this one is also valid:
2 3
5
1 4
but not this one:
4 1
3 2
5
In case of a malloc error your program will exit with the code 1.
We will not test with invalid sets (for example '1 1 2').
Hint: the empty subset is a valid subset of any set. It will be displayed as an empty line.
For example this should work:
$> ./powerset 3 1 0 2 4 5 3 | cat -e
3$
0 3$
1 2$
1 0 2$
$> ./powerset 12 5 2 1 8 4 3 7 11 | cat -e
8 4$
1 11$
1 4 7$
1 8 3$
2 3 7$
5 7$
5 4 3$
5 2 1 4$
$> ./powerset 0 1 -1 | cat -e
$
1 -1$
$> ./powerset 7 3 8 2 | cat -e
// Other tests:
$> ./powerset 100 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | cat -e
...
$> ./powerset -1 1 2 3 4 5 -10 | cat -e
...
$> ./powerset 0 -1 1 2 3 -2 | cat -e
...
$> ./powerset 13 65 23 3 4 6 7 1 2 | cat -e
...
$> ./powerset 10 0 1 2 3 4 5 6 7 8 9 | cat -e
...

View File

@ -1,80 +0,0 @@
# Program name
NAME = rip
# Compiler and flags
CC = gcc
CFLAGS = -Wall -Wextra -Werror
# Source files
SRCS = rip.c
# Object files
OBJS = $(SRCS:.c=.o)
# Colors for output
GREEN = \033[0;32m
RED = \033[0;31m
YELLOW = \033[0;33m
NC = \033[0m # No Color
# Default target
all: $(NAME)
# Build the executable
$(NAME): $(OBJS)
@echo "$(YELLOW)Linking $(NAME)...$(NC)"
@$(CC) $(CFLAGS) $(OBJS) -o $(NAME)
@echo "$(GREEN)$(NAME) created successfully!$(NC)"
# Compile source files to object files
%.o: %.c
@echo "$(YELLOW)Compiling $<...$(NC)"
@$(CC) $(CFLAGS) -c $< -o $@
# Clean object files
clean:
@echo "$(RED)🧹 Cleaning object files...$(NC)"
@rm -f $(OBJS)
@echo "$(GREEN)✅ Object files cleaned!$(NC)"
# Clean object files and executable
fclean: clean
@echo "$(RED)🧹 Cleaning executable...$(NC)"
@rm -f $(NAME)
@echo "$(GREEN)✅ Everything cleaned!$(NC)"
# Rebuild everything
re: fclean all
# Test the program with provided examples
test: $(NAME)
@echo "$(YELLOW)🧪 Running tests...$(NC)"
@echo "$(YELLOW)Test 1: '(()'$(NC)"
@./$(NAME) '(((' | cat -e
@echo "$(YELLOW)Test 2: '((()()())())'$(NC)"
@./$(NAME) '((()()())())' | cat -e
@echo "$(YELLOW)Test 3: '()())()''$(NC)"
@./$(NAME) '()())()' | cat -e
@echo "$(YELLOW)Test 4: '(()(()('$(NC)"
@./$(NAME) '(()(()(' | cat -e
@echo "$(GREEN)✅ All tests completed!$(NC)"
# Check for memory leaks (requires valgrind)
valgrind: $(NAME)
@echo "$(YELLOW)🔍 Checking for memory leaks...$(NC)"
@valgrind --leak-check=full --show-leak-kinds=all ./$(NAME) '(()'
@echo "$(GREEN)✅ Memory check completed!$(NC)"
# Show help
help:
@echo "$(GREEN)Available targets:$(NC)"
@echo " $(YELLOW)all$(NC) - Build the program"
@echo " $(YELLOW)clean$(NC) - Remove object files"
@echo " $(YELLOW)fclean$(NC) - Remove object files and executable"
@echo " $(YELLOW)re$(NC) - Rebuild everything (fclean + all)"
@echo " $(YELLOW)test$(NC) - Run all test cases"
@echo " $(YELLOW)valgrind$(NC) - Check for memory leaks"
@echo " $(YELLOW)help$(NC) - Show this help message"
# Declare phony targets
.PHONY: all clean fclean re test valgrind help

View File

@ -1,179 +0,0 @@
# The Parentheses Balancing Problem (RIP Exercise)
## What is this exercise about?
Imagine you have a string of parentheses like this: `"(()"`.
Think of parentheses like **doors** in a building:
- `(` is like **opening a door**
- `)` is like **closing a door**
For everything to work properly, every door you open must have a matching door that closes it!
## The Problem
Sometimes we get strings where the doors don't match properly. For example:
- `"((("` - We opened 3 doors but never closed any!
- `"())"` - We opened 1 door, closed 1 door, but then tried to close another door that was never opened!
Our job is to **fix** these strings by removing the minimum number of parentheses (but replacing them with spaces instead of deleting them completely).
## Real-World Example
Let's say you have: `"(()"`
This means:
1. Open door 1: `(`
2. Open door 2: `(`
3. Close door 2: `)`
4. But door 1 is still open! 😱
To fix this, we need to either:
- Remove one of the opening doors: ` ()` (remove first `(`)
- Or remove one of the opening doors: `( )` (remove second `(`)
Both solutions work!
## How Our Program Works
### Step 1: Count the Problems
```c
// This function counts how many parentheses we need to remove
void calculate_removals(char *str, int *left_rem, int *right_rem)
{
int left = 0; // Count of unmatched opening parentheses
int right = 0; // Count of unmatched closing parentheses
// Go through each character
while (str[i])
{
if (str[i] == '(')
left++; // Found an opening door
else if (str[i] == ')')
{
if (left > 0)
left--; // Found a closing door for an open one
else
right++; // Found a closing door with no matching open door
}
}
}
```
**Example with `"(()"`:**
- Start: `left = 0`, `right = 0`
- See `(`: `left = 1` (one unmatched opening)
- See `(`: `left = 2` (two unmatched openings)
- See `)`: `left = 1` (one opening got matched)
- End: `left = 1`, `right = 0`
So we need to remove **1 opening parenthesis**.
### Step 2: Try All Possible Solutions
Think of it like trying different combinations:
```c
// This function tries removing different parentheses to find all valid solutions
void solve(char *s, int pos, int left_rem, int right_rem, int open, char *path)
{
// If we've looked at all characters
if (pos == len)
{
// Check if we removed exactly what we needed and everything balances
if (left_rem == 0 && right_rem == 0 && open == 0)
add_result(results, path); // This is a valid solution!
return;
}
// Try removing this parenthesis (replace with space)
if (s[pos] == '(' && left_rem > 0)
{
path[pos] = ' '; // Replace with space
solve(s, pos + 1, left_rem - 1, right_rem, open, path);
}
// Try keeping this parenthesis
path[pos] = s[pos];
if (s[pos] == '(')
solve(s, pos + 1, left_rem, right_rem, open + 1, path);
// ... and so on
}
```
### Step 3: Avoid Duplicates
We use a list to store all unique solutions:
```c
// This makes sure we don't print the same solution twice
void add_result(t_result **results, char *str)
{
// Check if we already have this solution
current = *results;
while (current)
{
if (ft_strcmp(current->str, str) == 0)
return; // Already have it, don't add again
current = current->next;
}
// It's new, so add it to our list
new->str = ft_strdup(str);
new->next = *results;
*results = new;
}
```
## Example Walkthrough
Let's trace through `"(()"` step by step:
### Initial Analysis:
- Need to remove 1 opening parenthesis (`left_rem = 1`)
- Need to remove 0 closing parentheses (`right_rem = 0`)
### Trying Different Positions:
**Position 0 (first `(`):**
- Try removing it: `" ()"`
- Check: removed 1 opening ✓, no unmatched doors ✓
- **Valid solution!**
**Position 1 (second `(`):**
- Try removing it: `"( )"`
- Check: removed 1 opening ✓, no unmatched doors ✓
- **Valid solution!**
**Position 2 (the `)`):**
- Can't remove it (we need to remove openings, not closings)
### Final Output:
```
()
( )
```
## More Complex Example: `"()())()"`
This string has:
- 3 opening doors: `(`, `(`, `(`
- 4 closing doors: `)`, `)`, `)`, `)`
So we have 1 extra closing door that needs to be removed.
**All possible solutions:**
- Remove closing at position 2: `"()( )()"`
- Remove closing at position 3: `"()() ()"`
- Remove closing at position 4: `"( ())()"`
## Why This Exercise is Useful
This problem teaches us:
1. **Problem-solving**: Break down complex problems into smaller steps
2. **Recursion**: Try all possibilities systematically
3. **Data structures**: Use lists to store and manage results
4. **Optimization**: Find the minimum changes needed
It's like being a **door inspector** - you need to make sure every building (string) has properly matched doors (parentheses) with the minimum number of changes!

180
rip/rip.c
View File

@ -1,180 +0,0 @@
#include <unistd.h>
#include <stdlib.h>
typedef struct s_result
{
char *str;
struct s_result *next;
} t_result;
int ft_strlen(char *str)
{
int len;
len = 0;
while (str[len])
len++;
return (len);
}
int ft_strcmp(char *s1, char *s2)
{
int i;
i = 0;
while (s1[i] && s2[i] && s1[i] == s2[i])
i++;
return (s1[i] - s2[i]);
}
char *ft_strdup(char *src)
{
char *dup;
int len;
int i;
len = ft_strlen(src);
dup = malloc(len + 1);
if (!dup)
return (NULL);
i = 0;
while (i < len)
{
dup[i] = src[i];
i++;
}
dup[len] = '\0';
return (dup);
}
void add_result(t_result **results, char *str)
{
t_result *new;
t_result *current;
current = *results;
while (current)
{
if (ft_strcmp(current->str, str) == 0)
return ;
current = current->next;
}
new = malloc(sizeof(t_result));
if (!new)
return ;
new->str = ft_strdup(str);
if (!new->str)
{
free(new);
return ;
}
new->next = *results;
*results = new;
}
void print_results(t_result *results)
{
t_result *current;
int i;
current = results;
while (current)
{
i = 0;
while (current->str[i])
{
write(1, &current->str[i], 1);
i++;
}
write(1, "\n", 1);
current = current->next;
}
}
void free_results(t_result *results)
{
t_result *temp;
while (results)
{
temp = results;
results = results->next;
free(temp->str);
free(temp);
}
}
void solve(char *s, int pos, int left_rem, int right_rem, int open, char *path, t_result **results)
{
int len;
len = ft_strlen(s);
if (pos == len)
{
if (left_rem == 0 && right_rem == 0 && open == 0)
add_result(results, path);
return ;
}
if (s[pos] == '(' && left_rem > 0)
{
path[pos] = ' ';
solve(s, pos + 1, left_rem - 1, right_rem, open, path, results);
}
if (s[pos] == ')' && right_rem > 0)
{
path[pos] = ' ';
solve(s, pos + 1, left_rem, right_rem - 1, open, path, results);
}
path[pos] = s[pos];
if (s[pos] == '(')
solve(s, pos + 1, left_rem, right_rem, open + 1, path, results);
else if (s[pos] == ')' && open > 0)
solve(s, pos + 1, left_rem, right_rem, open - 1, path, results);
else
solve(s, pos + 1, left_rem, right_rem, open, path, results);
}
void remove_invalid_parentheses(char *s)
{
int left_rem;
int right_rem;
int len;
char *path;
int i;
t_result *results;
left_rem = 0;
right_rem = 0;
len = ft_strlen(s);
results = NULL;
i = 0;
while (s[i])
{
if (s[i] == '(')
left_rem++;
else if (s[i] == ')')
{
if (left_rem > 0)
left_rem--;
else
right_rem++;
}
i++;
}
path = malloc(len + 1);
if (!path)
return ;
path[len] = '\0';
solve(s, 0, left_rem, right_rem, 0, path, &results);
print_results(results);
free_results(results);
free(path);
}
int main(int argc, char **argv)
{
if (argc != 2)
return (1);
remove_invalid_parentheses(argv[1]);
return (0);
}

View File

@ -1,28 +0,0 @@
Assignment name : rip
Expected files : *.c *.h
Allowed functions: puts, write
--------------------------------------------------------------------------------
Write a program that will take as argument a string containing only parenthesis.
if the parenthesis are unbalanced (for example "())")
your program shall remove the minimum number of parentheses for the expression to be balanced.
By removing we mean replacing by spaces.
You will then print all the solutions (can be more than one).
The order of the solutions is not important.
For example this should work:
$> ./rip '(()' | cat -e
()$
( )$
$> ./rip '((()()())())' | cat -e
((()()())())$
$> ./rip '()())()'| cat -e
()() ()$
()( )()$
( ())()$
$> ./rip '(()(()(' | cat -e
(() ) $
( )( ) $
( ) () $
()( ) $

View File

@ -1,26 +0,0 @@
NAME = tsp
SRCS = tsp.c
OBJS = $(SRCS:.c=.o)
CC = gcc
CFLAGS = -Wall -Wextra -Werror
MATH_FLAGS = -lm
all: $(NAME)
$(NAME): $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o $(NAME) $(MATH_FLAGS)
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -f $(OBJS)
fclean: clean
rm -f $(NAME)
re: fclean all
.PHONY: all clean fclean re

View File

@ -1,247 +0,0 @@
# The Traveling Salesman Problem (TSP) - Simple Explanation
## What is the Traveling Salesman Problem? 🗺️
Imagine you're a delivery person who needs to visit several houses in your neighborhood and then return home. You want to find the **shortest possible route** that visits every house exactly once and brings you back to where you started.
That's exactly what the Traveling Salesman Problem is about!
### Real-World Example
Let's say you need to deliver pizza to 4 houses:
- Your home: (0, 0)
- House A: (1, 0)
- House B: (1, 1)
- House C: (0, 1)
```
C ---- B
| |
| |
Home - A
```
You could go in many different orders:
- Home → A → B → C → Home
- Home → A → C → B → Home
- Home → B → A → C → Home
- ... and many more!
But which path is the shortest? That's what our algorithm finds out!
## How Our Algorithm Works 🔍
Our solution uses a "brute force" approach, which means:
**"Let's try EVERY possible path and pick the shortest one!"**
It's like trying on every shirt in your closet to find the one that fits best - not the fastest way, but it guarantees you'll find the perfect answer!
### Step 1: Calculate Distance Between Two Points
First, we need to know how far apart two places are:
```c
static float distance(t_city a, t_city b)
{
float dx = b.x - a.x; // How far left/right?
float dy = b.y - a.y; // How far up/down?
return (sqrtf(dx * dx + dy * dy)); // Pythagorean theorem!
}
```
**What's happening here?**
- `dx` = horizontal distance (like counting steps left or right)
- `dy` = vertical distance (like counting steps up or down)
- `sqrtf(dx*dx + dy*dy)` = the straight-line distance (like a bird flying)
**Example:**
From Home (0,0) to House A (1,0):
- dx = 1 - 0 = 1
- dy = 0 - 0 = 0
- distance = √(1² + 0²) = √1 = 1.0
### Step 2: Calculate Total Path Length
Now we add up all the distances in a complete round trip:
```c
static float path_length(t_city *cities, int *route, int n)
{
float total = 0;
int i = 0;
while (i < n)
{
// Add distance from current city to next city
total += distance(cities[route[i]], cities[route[(i + 1) % n]]);
i++;
}
return (total);
}
```
**What's that weird `% n` thing?**
It's like a clock! When you get to hour 12, the next hour is 1, not 13.
- When `i = 3` (last city) and `n = 4` (total cities)
- `(i + 1) % n = (3 + 1) % 4 = 4 % 4 = 0`
- So we go from the last city back to the first city (completing the circle!)
### Step 3: Try All Possible Routes
This is where the magic happens! We generate every possible order of visiting the cities:
```c
static void solve(t_city *cities, int *route, int pos, int n, float *best)
{
float current;
int i, temp;
// If we've arranged all cities, check this route
if (pos == n)
{
current = path_length(cities, route, n);
if (current < *best)
*best = current; // Found a better route!
return;
}
// Try putting each remaining city in the current position
i = pos;
while (i < n)
{
// Swap cities (like switching the order of your visits)
temp = route[pos];
route[pos] = route[i];
route[i] = temp;
// Try all arrangements with this city in this position
solve(cities, route, pos + 1, n, best);
// Swap back (undo the change)
temp = route[pos];
route[pos] = route[i];
route[i] = temp;
i++;
}
}
```
**Think of it like this:**
- Position 0: "Which city should I visit first?"
- Position 1: "Which city should I visit second?"
- Position 2: "Which city should I visit third?"
- And so on...
For each position, we try putting each remaining city there and see what happens!
## Complete Example Walkthrough 🚶‍♂️
Let's trace through a simple 3-city example:
- City 0: (0, 0)
- City 1: (1, 0)
- City 2: (0, 1)
```
2
|
|
0 --- 1
```
**All possible routes:**
1. 0 → 1 → 2 → 0: distance = 1 + √2 + 1 = 3.41
2. 0 → 2 → 1 → 0: distance = 1 + √2 + 1 = 3.41
3. 1 → 0 → 2 → 1: distance = 1 + 1 + √2 = 3.41
4. 1 → 2 → 0 → 1: distance = √2 + 1 + 1 = 3.41
5. 2 → 0 → 1 → 2: distance = 1 + 1 + √2 = 3.41
6. 2 → 1 → 0 → 2: distance = √2 + 1 + 1 = 3.41
**Result:** All routes have the same length! (This makes sense - it's a triangle, so any direction around it is the same distance.)
## The Main Program 🏠
```c
int main(void)
{
t_city cities[11]; // Space for up to 11 cities
int route[11]; // The order we'll visit cities
int n = 0; // How many cities we actually have
float best = 999999.0f; // Start with a really big number
// Read city coordinates from input
while (n < 11 && fscanf(stdin, "%f, %f", &cities[n].x, &cities[n].y) == 2)
{
route[n] = n; // Initially: visit cities in order 0,1,2,3...
n++;
}
if (n < 2)
return (1); // Need at least 2 cities for a trip!
solve(cities, route, 0, n, &best); // Find the best route
fprintf(stdout, "%.2f\n", best); // Print the shortest distance
return (0);
}
```
## Why This Works (But Is Slow) ⏰
**The Good:**
- ✅ **Always finds the perfect answer** - we check every possibility!
- ✅ **Simple to understand** - no complex tricks or shortcuts
- ✅ **Works for any arrangement of cities**
**The Not-So-Good:**
- ❌ **Gets very slow with more cities**
- For 3 cities: 6 routes to check
- For 4 cities: 24 routes to check
- For 10 cities: 3,628,800 routes to check! 😱
**Why it gets so big:**
- 1st city: 10 choices
- 2nd city: 9 choices (can't repeat)
- 3rd city: 8 choices
- ...
- Total: 10 × 9 × 8 × 7 × 6 × 5 × 4 × 3 × 2 × 1 = 3,628,800
This is called "factorial growth" - it explodes very quickly!
## Key Programming Concepts Used 💻
### 1. **Recursion**
The `solve()` function calls itself! It's like Russian nesting dolls - each call handles one position, then asks a smaller version of itself to handle the rest.
### 2. **Backtracking**
We try something (swap cities), explore all possibilities, then undo it (swap back). Like trying different paths in a maze and backing up when we hit a dead end.
### 3. **Permutations**
We generate every possible ordering of the cities. It's like having cards numbered 1,2,3 and arranging them in every possible order: 123, 132, 213, 231, 312, 321.
### 4. **Global Optimization**
We keep track of the best solution found so far and update it whenever we find something better.
## Fun Facts! 🎯
1. **This problem is NP-hard** - that's computer science speak for "really, really hard to solve quickly"
2. **Real delivery companies** use approximate algorithms that find "pretty good" solutions much faster than perfect ones
3. **With 11 cities** (the maximum our program handles), there are 39,916,800 possible routes!
4. **The problem has applications** in:
- GPS navigation systems
- Circuit board manufacturing
- DNA sequencing
- Planning efficient tours for bands or sports teams
## Summary 📝
Our TSP algorithm is like a very thorough friend who insists on checking every possible pizza delivery route before deciding which one is shortest. It's not the fastest approach, but it guarantees the perfect answer!
The main steps are:
1. **Read** all the city locations
2. **Generate** every possible visiting order
3. **Calculate** the total distance for each order
4. **Remember** the shortest distance found
5. **Print** the answer
Even though it's not the most efficient algorithm for large problems, it's perfect for learning because it's easy to understand and always gives the correct answer! 🎉

View File

@ -1,8 +0,0 @@
0, 0
1, 0
2, 0
0, 1
1, 1
2, 1
5, 2
2, 2

View File

@ -1,64 +0,0 @@
Assignment name: tsp
Expected files: *.c *.h
Allowed functions: write, sqrtf, getline, fseek, fscanf, ferror, feof,
fabsf, memcpy, fprintf, fclose, malloc, calloc, realloc, free, fopen,
errno, stderr, stdin, stdout
-------------------------------------------------------
The first publication referring to this problem as the "traveling salesman
problem" is found in the 1949 RAND Corporation report by Julia Robinson,
"On the Hamiltonian game (a traveling salesman problem)."
Here is how she defines the problem:
"The purpose of this note is to give a method for solving a problem related
to the traveling salesman problem. It seems worthwhile to give a description
of the original problem. One formulation is to find the shortest route for a
salesman starting from Washington, visiting all the state capitals and then
returning to Washington.
More generally, to find the shortest CLOSED CURVE containing n given points
in the plane."
for example with the following set of cities:
0, 0
1, 0
2, 0
0, 1
1, 1
2, 1
1, 2
2, 2
which can be presented as follows:
+ + +
+ + +
+ +
the shortest path is:
_____
|__ |
|__|
so you should print the length of this path that is:
8.00
Write a program that will read a set of city coordinates in the form
'%f, %f\n' from the standard input and will print the length of the shortest
possible path containing all these cities under the form '%.2f'.
Your program will not be tested with more than 11 cities.
You will find in this directory a file tsp.c containing all the boring parts of
this exercise and example files to help you test your program.
hint: in order to use sqrtf, add -lm at the end of your compilation command.
For example this should work:
$> cat square.txt
1, 1
0, 1
1, 0
0, 0
$> ./tsp < square.txt | cat -e
4.00$
Hint : in order to use sqrtf , add -lm at the end of your compilation command

View File

@ -1,66 +0,0 @@
#include "tsp.h"
static float distance(t_city a, t_city b)
{
float dx = b.x - a.x;
float dy = b.y - a.y;
return (sqrtf(dx * dx + dy * dy));
}
static float path_length(t_city *cities, int *route, int n)
{
float total = 0;
int i = 0;
while (i < n)
{
total += distance(cities[route[i]], cities[route[(i + 1) % n]]);
i++;
}
return (total);
}
static void solve(t_city *cities, int *route, int pos, int n, float *best)
{
float current;
int i, temp;
if (pos == n)
{
current = path_length(cities, route, n);
if (current < *best)
*best = current;
return;
}
i = pos;
while (i < n)
{
temp = route[pos];
route[pos] = route[i];
route[i] = temp;
solve(cities, route, pos + 1, n, best);
temp = route[pos];
route[pos] = route[i];
route[i] = temp;
i++;
}
}
int main(void)
{
t_city cities[11];
int route[11];
int n = 0;
float best = 999999.0f;
while (n < 11 && fscanf(stdin, "%f, %f", &cities[n].x, &cities[n].y) == 2)
{
route[n] = n;
n++;
}
if (n < 2)
return (1);
solve(cities, route, 0, n, &best);
fprintf(stdout, "%.2f\n", best);
return (0);
}

View File

@ -1,14 +0,0 @@
#ifndef TSP_H
# define TSP_H
# include <stdio.h>
# include <stdlib.h>
# include <math.h>
typedef struct s_city
{
float x;
float y;
} t_city;
#endif