Added permutations and powerset

This commit is contained in:
Rui Ribeiro 2025-09-30 13:13:09 +00:00
parent eb777e722d
commit 2b362d0916
2 changed files with 106 additions and 175 deletions

View File

@ -1,132 +1,60 @@
#include <unistd.h> // write #include <stdlib.h>
#include <stdlib.h> // malloc, free #include <stdio.h>
// Função auxiliar para obter o comprimento de uma string int length;
int ft_strlen(const char *s) char *set;
{ char *permutation;
int len = 0;
while (s[len])
len++;
return (len);
}
// Função auxiliar para imprimir uma string seguida de uma nova linha int ft_strlen(char *s)
void print_solution(const char *s)
{ {
write(1, s, ft_strlen(s)); int i = 0;
write(1, "\n", 1); while(s[i])
}
// Função auxiliar para trocar dois caracteres (usada na ordenação)
void ft_swap(char *a, char *b)
{
char temp = *a;
*a = *b;
*b = temp;
}
// Função para ordenar a string de entrada (Bubble Sort simples)
// Isso é crucial para garantir que as permutações sejam geradas em ordem alfabética.
void sort_string(char *str, int n)
{
int i;
int j;
i = 0;
while (i < n - 1)
{
j = 0;
while (j < n - i - 1)
{
if (str[j] > str[j + 1])
ft_swap(&str[j], &str[j + 1]);
j++;
}
i++; i++;
} return (i);
} }
// A função principal de backtracking, análoga à sua função `solve`
// Parâmetros: void permutations(int index, char *used)
// - original_str: A string original, já ordenada
// - current_perm: A permutação que estamos construindo (o "tabuleiro")
// - used: Um array que marca quais caracteres da string original já foram usados
// - n: O tamanho da string
// - k: A posição atual que estamos preenchendo em `current_perm` (análogo a `col`)
void generate_permutations(char *original_str, char *current_perm, int *used, int n, int k)
{ {
// Caso base: Se todas as posições foram preenchidas (k == n), if (index == length)
// análogo a `if (col == n)` no N-Queens.
if (k == n)
{ {
print_solution(current_perm); printf("%s\n", permutation);
return ; return ;
} }
// Tenta colocar cada caractere da string original na posição 'k' atual
int i = 0; int i = 0;
while (i < n) while (i < length)
{ {
// Verifica se a "jogada" é válida, análogo ao `is_safe`. if (used[i] == '0')
// A condição é: o i-ésimo caractere da string original ainda não foi usado?
if (used[i] == 0)
{ {
// "Coloca a peça no tabuleiro": permutation[index] = set[i];
// 1. Coloca o caractere na permutação atual used[i] = '1';
current_perm[k] = original_str[i]; permutations(index + 1, used);
// 2. Marca este caractere como usado used[i] = '0';
used[i] = 1;
// Chama a função recursivamente para a próxima posição (k + 1),
// análogo a `solve(board, n, col + 1)`
generate_permutations(original_str, current_perm, used, n, k + 1);
// Backtracking: Desfaz a jogada para que este caractere possa ser
// usado em uma posição diferente na próxima ramificação da recursão.
// Isso é crucial e um pouco mais explícito que no seu N-Queens.
used[i] = 0;
} }
i++; i++;
} }
} }
int main(int argc, char **argv) char *populate_used()
{ {
if (argc != 2 || !argv[1][0]) char *ret = (char *) calloc (length + 1, sizeof(char));
{ int i = 0;
// Não faz nada se não houver exatamente um argumento ou se for uma string vazia. while (i < length)
return (0); ret[i++] = '0';
return (ret);
} }
int n = ft_strlen(argv[1]); int main(int ac, char **av)
char *original_str = argv[1]; // Não precisamos de cópia, podemos ordenar o argumento
// 1. Ordena a string de entrada para garantir a saída em ordem alfabética
sort_string(original_str, n);
// 2. Aloca memória para a permutação que será construída
char *current_perm = (char *)malloc(sizeof(char) * (n + 1));
if (!current_perm)
return (1);
current_perm[n] = '\0'; // Garante a terminação da string
// 3. Aloca memória para o array de "usados" e o inicializa com 0
// `calloc` é útil aqui pois inicializa a memória com zeros.
int *used = (int *)malloc(sizeof(int) * n);
if (!used)
{ {
free(current_perm); if (ac != 2)
return (1); return (1);
} set = av[1];
for (int i = 0; i < n; i++) length = ft_strlen(av[1]);
used[i] = 0; char *used = populate_used();
permutation = (char *) malloc(sizeof(char) * (length + 1));
// Inicia o processo de backtracking a partir da primeira posição (k = 0) permutations(0, used);
generate_permutations(original_str, current_perm, used, n, 0);
// Liberta a memória alocada
free(current_perm);
free(used); free(used);
free(permutation);
return (0); return (0);
} }

View File

@ -1,68 +1,71 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
void print_subset(int *subset, int size) int target;
{ int length;
int i; int *set;
i = 0; void populate_array(int ac, char **av)
while (i < size)
{ {
printf("%d", subset[i]); int i = 0;
if (i < size - 1) int j = 2;
printf(" "); while(j < ac)
{
set[i] = atoi(av[j]);
i++;
j++;
}
}
void print_set(int *used)
{
int i = 0;
int is_first = 1;
while(i < length)
{
if (used[i] == 1)
{
if (is_first)
{
fprintf(stdout, "%i", set[i]);
is_first = 0;
}
else
fprintf(stdout, " %i", set[i]);
}
i++; i++;
} }
printf("\n"); printf("\n");
} }
void find_subsets(int target, int *set, int set_size, int index, int *current_path, int path_len) void powerset(int index, int current_sum, int *used)
{ {
if (target == 0) if (index == length)
return (print_subset(current_path, path_len)); {
if (current_sum == target)
if (index >= set_size) print_set(used);
return ; return ;
current_path[path_len] = set[index];
find_subsets(target - set[index], set, set_size, index + 1, current_path, path_len + 1);
find_subsets(target, set, set_size, index + 1, current_path, path_len);
} }
int main(int argc, char **argv) powerset(index + 1, current_sum, used);
used[index] = 1;
powerset(index + 1, current_sum + set[index], used);
used[index] = 0;
}
int main(int ac, char **av)
{ {
int target; if (ac < 2)
int *numbers;
int *path;
int size;
int i;
if (argc < 2)
return (0);
target = atoi(argv[1]);
size = argc - 2;
numbers = (int *)malloc(sizeof(int) * size);
if (!numbers)
return (1); return (1);
path = (int *)malloc(sizeof(int) * size); length = ac -2;
if (!path) target = atoi(av[1]);
{ set = (int *) malloc (sizeof(int) * length);
free(numbers); int *used = (int *) calloc (length, sizeof(int));
return (1); populate_array(ac, av);
} powerset(0, 0, used);
i = 0; free(set);
while (i < size) free(used);
{
numbers[i] = atoi(argv[i + 2]);
i++;
}
find_subsets(target, numbers, size, 0, path, 0);
free(numbers);
free(path);
return (0); return (0);
} }