132 lines
3.5 KiB
C
132 lines
3.5 KiB
C
#include <unistd.h> // write
|
|
#include <stdlib.h> // malloc, free
|
|
|
|
// Função auxiliar para obter o comprimento de uma string
|
|
int ft_strlen(const char *s)
|
|
{
|
|
int len = 0;
|
|
while (s[len])
|
|
len++;
|
|
return (len);
|
|
}
|
|
|
|
// Função auxiliar para imprimir uma string seguida de uma nova linha
|
|
void print_solution(const char *s)
|
|
{
|
|
write(1, s, ft_strlen(s));
|
|
write(1, "\n", 1);
|
|
}
|
|
|
|
// 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++;
|
|
}
|
|
}
|
|
|
|
// A função principal de backtracking, análoga à sua função `solve`
|
|
// Parâmetros:
|
|
// - 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),
|
|
// análogo a `if (col == n)` no N-Queens.
|
|
if (k == n)
|
|
{
|
|
print_solution(current_perm);
|
|
return;
|
|
}
|
|
|
|
// Tenta colocar cada caractere da string original na posição 'k' atual
|
|
int i = 0;
|
|
while (i < n)
|
|
{
|
|
// Verifica se a "jogada" é válida, análogo ao `is_safe`.
|
|
// 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":
|
|
// 1. Coloca o caractere na permutação atual
|
|
current_perm[k] = original_str[i];
|
|
// 2. Marca este caractere como usado
|
|
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++;
|
|
}
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
if (argc != 2 || !argv[1][0])
|
|
{
|
|
// Não faz nada se não houver exatamente um argumento ou se for uma string vazia.
|
|
return (0);
|
|
}
|
|
|
|
int n = ft_strlen(argv[1]);
|
|
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);
|
|
return (1);
|
|
}
|
|
for (int i = 0; i < n; i++)
|
|
used[i] = 0;
|
|
|
|
// Inicia o processo de backtracking a partir da primeira posição (k = 0)
|
|
generate_permutations(original_str, current_perm, used, n, 0);
|
|
|
|
// Liberta a memória alocada
|
|
free(current_perm);
|
|
free(used);
|
|
|
|
return (0);
|
|
} |