From f755b9a48178563ec24dcf76f6101ddcc67e91b0 Mon Sep 17 00:00:00 2001 From: Rui Ribeiro <42305006+ruiribeiro04@users.noreply.github.com> Date: Mon, 22 Sep 2025 16:55:06 +0100 Subject: [PATCH] added permutations --- permutations/Makefile | 25 +++++ permutations/README.md | 200 ++++++++++++++++++++++++++++++++++++ permutations/permutations.c | 98 ++++++++++++++++++ permutations/permutations.h | 14 +++ permutations/subject.txt | 27 +++++ 5 files changed, 364 insertions(+) create mode 100644 permutations/Makefile create mode 100644 permutations/README.md create mode 100644 permutations/permutations.c create mode 100644 permutations/permutations.h create mode 100644 permutations/subject.txt diff --git a/permutations/Makefile b/permutations/Makefile new file mode 100644 index 0000000..cc23f7c --- /dev/null +++ b/permutations/Makefile @@ -0,0 +1,25 @@ +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 new file mode 100644 index 0000000..4621e13 --- /dev/null +++ b/permutations/README.md @@ -0,0 +1,200 @@ +# 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 new file mode 100644 index 0000000..7903081 --- /dev/null +++ b/permutations/permutations.c @@ -0,0 +1,98 @@ +#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 new file mode 100644 index 0000000..1ee8c38 --- /dev/null +++ b/permutations/permutations.h @@ -0,0 +1,14 @@ +#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 new file mode 100644 index 0000000..52fece3 --- /dev/null +++ b/permutations/subject.txt @@ -0,0 +1,27 @@ +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