diff --git a/n_queens/Makefile b/n_queens/Makefile deleted file mode 100644 index 268ca72..0000000 --- a/n_queens/Makefile +++ /dev/null @@ -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 \ No newline at end of file diff --git a/n_queens/README.md b/n_queens/README.md deleted file mode 100644 index 2d5a27b..0000000 --- a/n_queens/README.md +++ /dev/null @@ -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! ๐Ÿš€ \ No newline at end of file diff --git a/n_queens/n_queens.c b/n_queens/n_queens.c deleted file mode 100644 index 45d7340..0000000 --- a/n_queens/n_queens.c +++ /dev/null @@ -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); -} \ No newline at end of file diff --git a/n_queens/n_queens.h b/n_queens/n_queens.h deleted file mode 100644 index 47d8053..0000000 --- a/n_queens/n_queens.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef N_QUEENS_H -# define N_QUEENS_H - -# include -# include -# include - -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 \ No newline at end of file diff --git a/n_queens/subject.txt b/n_queens/subject.txt deleted file mode 100644 index 9957439..0000000 --- a/n_queens/subject.txt +++ /dev/null @@ -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 : - ... \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... \ No newline at end of file diff --git a/permutations/Makefile b/permutations/Makefile deleted file mode 100644 index cc23f7c..0000000 --- a/permutations/Makefile +++ /dev/null @@ -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 \ No newline at end of file diff --git a/permutations/README.md b/permutations/README.md deleted file mode 100644 index 4621e13..0000000 --- a/permutations/README.md +++ /dev/null @@ -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!* \ No newline at end of file diff --git a/permutations/permutations.c b/permutations/permutations.c deleted file mode 100644 index 7903081..0000000 --- a/permutations/permutations.c +++ /dev/null @@ -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); -} \ No newline at end of file diff --git a/permutations/permutations.h b/permutations/permutations.h deleted file mode 100644 index 1ee8c38..0000000 --- a/permutations/permutations.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef PERMUTATIONS_H -# define PERMUTATIONS_H - -# include -# include -# include - -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 \ No newline at end of file diff --git a/permutations/subject.txt b/permutations/subject.txt deleted file mode 100644 index 52fece3..0000000 --- a/permutations/subject.txt +++ /dev/null @@ -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$ \ No newline at end of file diff --git a/powerset/Makefile b/powerset/Makefile deleted file mode 100644 index d3fa3ab..0000000 --- a/powerset/Makefile +++ /dev/null @@ -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 \ No newline at end of file diff --git a/powerset/README.md b/powerset/README.md deleted file mode 100644 index ef51e34..0000000 --- a/powerset/README.md +++ /dev/null @@ -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?* ๐Ÿค–โœจ \ No newline at end of file diff --git a/powerset/powerset.c b/powerset/powerset.c deleted file mode 100644 index 851f4af..0000000 --- a/powerset/powerset.c +++ /dev/null @@ -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); -} \ No newline at end of file diff --git a/powerset/powerset.h b/powerset/powerset.h deleted file mode 100644 index 1fe88c2..0000000 --- a/powerset/powerset.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef POWERSET_H -# define POWERSET_H - -# include -# include -# include - -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 \ No newline at end of file diff --git a/powerset/subject.txt b/powerset/subject.txt deleted file mode 100644 index 4e2911a..0000000 --- a/powerset/subject.txt +++ /dev/null @@ -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 -... \ No newline at end of file diff --git a/rip/Makefile b/rip/Makefile deleted file mode 100644 index aeff5b2..0000000 --- a/rip/Makefile +++ /dev/null @@ -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 \ No newline at end of file diff --git a/rip/README.md b/rip/README.md deleted file mode 100644 index 84671e4..0000000 --- a/rip/README.md +++ /dev/null @@ -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! \ No newline at end of file diff --git a/rip/rip.c b/rip/rip.c deleted file mode 100644 index 960ae96..0000000 --- a/rip/rip.c +++ /dev/null @@ -1,180 +0,0 @@ -#include -#include - -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, ¤t->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); -} \ No newline at end of file diff --git a/rip/subject.txt b/rip/subject.txt deleted file mode 100644 index 0958bd5..0000000 --- a/rip/subject.txt +++ /dev/null @@ -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 -(() ) $ -( )( ) $ -( ) () $ - ()( ) $ \ No newline at end of file diff --git a/tsp/Makefile b/tsp/Makefile deleted file mode 100644 index dc5ca14..0000000 --- a/tsp/Makefile +++ /dev/null @@ -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 \ No newline at end of file diff --git a/tsp/TSP_Algorithm_Explained.md b/tsp/TSP_Algorithm_Explained.md deleted file mode 100644 index 42531ed..0000000 --- a/tsp/TSP_Algorithm_Explained.md +++ /dev/null @@ -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! ๐ŸŽ‰ \ No newline at end of file diff --git a/tsp/square.txt b/tsp/square.txt deleted file mode 100644 index 1673c5b..0000000 --- a/tsp/square.txt +++ /dev/null @@ -1,8 +0,0 @@ -0, 0 -1, 0 -2, 0 -0, 1 -1, 1 -2, 1 -5, 2 -2, 2 \ No newline at end of file diff --git a/tsp/subject.txt b/tsp/subject.txt deleted file mode 100644 index afc2bf0..0000000 --- a/tsp/subject.txt +++ /dev/null @@ -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 \ No newline at end of file diff --git a/tsp/tsp.c b/tsp/tsp.c deleted file mode 100644 index 7bb869f..0000000 --- a/tsp/tsp.c +++ /dev/null @@ -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); -} \ No newline at end of file diff --git a/tsp/tsp.h b/tsp/tsp.h deleted file mode 100644 index 8d0091d..0000000 --- a/tsp/tsp.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef TSP_H -# define TSP_H - -# include -# include -# include - -typedef struct s_city -{ - float x; - float y; -} t_city; - -#endif \ No newline at end of file