Um anagrama de uma palavra é uma permutação das suas letras a fim de formar uma outra palavra. Por exemplo, ator é um anagrama da palavra rota.
A saída deve conter todos os anagramas possíveis, sem repetições e em ordem alfabética, para uma palavra através de uma função recursiva que deve ser implementada em um arquivo separado da main.
Exemplo de entrada:
ave
Exemplo de saída:
aev
ave
eav
eva
vae
vea
Arquivo com a função recursiva geradora dos anagramas:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*Função generate:
* Entrada:
* string_ordenada: a string original, que devemos processar para encontrarmos todos os anagramas
* letra_usada: um vetor de booleanos (implementado da forma de um vetor de inteiros) para marcarmos quais posições da string original já foram usadas
* word: o anagrama que estamos formando
* n: o numero de letras do anagrama
* k: a posição onde incluiremos a proxima letra em word
*
* A ideia para gerar sem repeticoes eh que setada a letra da posicao k,
* e retornado da chamada recursiva, temos que colocar uma letra diferente na posição k,
* pois senão geraríamos as repetições. Quando n==k incluimos a letra faltante e imprimimos o
* anagrama.
*/
void generate(char *string_ordenada, int *letra_usada, char *word, int n, int k){
if(k<n){//Se há mais letras a ser adicionada (quando k é menor que n):
for(int i=0; i<n;i++)//Percorre o vetor booleano de quais letras foram usadas e quais não
if(letra_usada[i]==0){//Se a letra na posição i não foi usada:
letra_usada[i] = 1;//Marque-a como usada,
word[k] = string_ordenada[i];//Armazene em word na posição k a letra correspondente,
generate(string_ordenada, letra_usada, word, n, k+1);//E chame a própria função.
letra_usada[i]=0;//Torne a letra atual como não usada,
for(;string_ordenada[i] == string_ordenada[i+1];i++);//E verifique qual é a próxima letra que seja diferente da atual, avançando a posição i.
}
}else{//Caso já todas as letras tenham sido usadas:
word[n]='\0';//Adicione o '\0', indicador de fim da string,
printf("%s\n",word);//E imprima a string/palavra/anagrama formado.
}
}
No código abaixo, que, novamente, seria um arquivo separado, temos nossa função main (de autoria dos PEDs do IC-Unicamp):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
A ideia para gerar sem repeticoes e que setado a letra da posicao k,
geramos todas as possibilidades e quando voltar do backtracking temos
que colocar uma letra diferente na posição k, pois senão geraríamos
as repetições. Por isso depois de setado uma posição a próxima letra
da posição é dado por proxima_letra_diferente que discarta letras iguais a já setada.
*/
void generate(char *string_ordenada, int *letra_usada, char *word, int n, int k);
char * sort(char string[]);
int main(){
char *string_inicial;
string_inicial = (char*) malloc(sizeof(char));
int string_inicial_tam = 0;
char c;
while(scanf("%c", &c) && c != '\n') {
string_inicial_tam++;
string_inicial = (char*) realloc(string_inicial, string_inicial_tam+1 * sizeof(char));
string_inicial[string_inicial_tam-1] = c;
string_inicial[string_inicial_tam] = '\0';
}
char *string_ordenada = sort(string_inicial);
int n = strlen(string_ordenada);
int *letra_usada = malloc(n*sizeof(int));
char *anagrama = malloc((n+1)*sizeof(char));
int i=0;
for(i=0; i<n; i++)
letra_usada[i]=0;
generate(string_ordenada, letra_usada, anagrama, n, 0);
free(anagrama);
free(string_ordenada);
free(letra_usada);
}
char * sort(char string[]){
int count[256], i;
char *sr;
for(i=0; i<256; i++)
count[i] = 0;
i=0;
while(string[i] != '\0'){
count[(int)string[i]]++;
i++;
}
sr = malloc((i+1)*sizeof(char));
int j=0, k=0;
for(i=0; i<256; i++){
if(count[i]!=0){
for(k=0; k<count[i]; k++){
sr[j] = i;
j++;
}
}
}
sr[j] = '\0';
return sr;
}