#include // write #include // 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); }