added powerset
This commit is contained in:
parent
36a3a5a8aa
commit
393bcc3028
83
powerset/Makefile
Normal file
83
powerset/Makefile
Normal file
@ -0,0 +1,83 @@
|
||||
# **************************************************************************** #
|
||||
# #
|
||||
# ::: :::::::: #
|
||||
# Makefile :+: :+: :+: #
|
||||
# +:+ +:+ +:+ #
|
||||
# By: ruiferna <ruiferna@student.42porto.com> +#+ +:+ +#+ #
|
||||
# +#+#+#+#+#+ +#+ #
|
||||
# Created: 2025/09/22 00:00:00 by ruiferna #+# #+# #
|
||||
# Updated: 2025/09/22 17:15:15 by ruiferna ### ########.fr #
|
||||
# #
|
||||
# **************************************************************************** #
|
||||
|
||||
# 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
|
||||
175
powerset/README.md
Normal file
175
powerset/README.md
Normal file
@ -0,0 +1,175 @@
|
||||
# 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?* 🤖✨
|
||||
85
powerset/powerset.c
Normal file
85
powerset/powerset.c
Normal file
@ -0,0 +1,85 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* powerset.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: ruiferna <ruiferna@student.42porto.com> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/09/22 00:00:00 by ruiferna #+# #+# */
|
||||
/* Updated: 2025/09/22 17:12:50 by ruiferna ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#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);
|
||||
}
|
||||
24
powerset/powerset.h
Normal file
24
powerset/powerset.h
Normal file
@ -0,0 +1,24 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* powerset.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: ruiferna <ruiferna@student.42porto.com> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/09/22 00:00:00 by ruiferna #+# #+# */
|
||||
/* Updated: 2025/09/22 17:12:51 by ruiferna ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#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
|
||||
65
powerset/subject.txt
Normal file
65
powerset/subject.txt
Normal file
@ -0,0 +1,65 @@
|
||||
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
|
||||
...
|
||||
Loading…
Reference in New Issue
Block a user