001: #include<stdio.h>
002: #include<stdlib.h>
003: #include<string.h>
004: #include<time.h>
005: 
006: #define NALPHA ('z' - 'a' + 1 )
007: #define NLETTERS 12
008: 
009: void riempi_freqs(double f[]);
010: char estrai_lettera(const double f[]);
011: int verifica_parola(char lettere[], const char parola[]);
012: int verifica_dizionario(const char parola[]);
013: 
014: int main(int argc, char **argv){
015: 
016:    /* PUNTO 1 */
017:   double freqs[NALPHA];  // banalmente memorizzo le frequenze in array da 26 double (anche float ci stava), calcolando gia' la somma
018:                          // quindi:
019:                          // indice elemento -> lettera, ovvero 0='a', 1='b' ...
020:                          // valore elemento -> somma frequenze fino a quella lettera
021:   riempi_freqs(freqs); // leggo file e lo memorizzo
022: 
023:   /* PUNTO 2 */
024:   srand(time(0));
025:   // DEBUG
026:   //printf("Test funzione estrai_lettera(), la richiamo e mi restituisce %c\n", estrai_lettera(freqs));
027: 
028:   /* PUNTO 3 */
029:   char lettere[NLETTERS+1]; // stringa che conterra' le lettere estratte a caso
030:   int i;
031:   for(i=0; i<NLETTERS; ++i)
032:     lettere[i]=estrai_lettera(freqs); // la riempo con lettere estratte a caso
033:   lettere[NLETTERS-1] = '\0'; // termino la stringa inserendo nell'ultimo elemento dell'array il carattere di "fine stringa"
034: 
035:   printf("Le lettere estratte sono [ %s ]\n", lettere);
036: 
037:   /* PUNTO 4 */
038:   char parola[NLETTERS+1]; // dove memorizzo la parola letta da input
039:   printf("Componi una parola con le lettere estratte: ");
040:   scanf("%s", parola);
041: 
042:   /* PUNTO 5 */
043:   int valid = verifica_parola(lettere, parola);
044:   if(!valid)
045:   {
046:     printf("Ahi! ahi! la parola inserita non si puo' comporre con le lettere che ti ho dato io.\n");
047:     exit(-1);
048:   }
049: 
050:   /* PUNTO 6 */
051:   valid = verifica_dizionario(parola);
052:   if(!valid)
053:   {
054:     printf("Ahi! ahi! la parola inserita non esiste.\n");
055:     exit(-1);
056:   }
057: 
058:   printf("Complimenti, hai fatto tutto giusto: %ld punti.\n", strlen(parola));
059: 
060:   return 0;
061: }
062: 
063: void riempi_freqs(double f[])
064: {
065:   int i;
066:   double ftmp;
067:   char tmp;
068: 
069:   FILE *fp=fopen("letterfreq.txt", "r"); // apro relativo file in lettura
070:   if(!fp)
071:   {
072:     perror("");
073:     exit(EXIT_FAILURE);
074:   }
075: 
076:   fscanf(fp, " %c %lf", &tmp, &f[0]); // leggo i dati di a, dato che i valori sono in ordine ignoro del tutto la lettera
077: 
078:   for(i=1; i<NALPHA; ++i)
079:   {
080:     fscanf(fp, " %c %lf", &tmp, &ftmp); // leggo i dati delle lettere successive
081:     f[i] = f[i-1] + ftmp;
082:   }
083:   fclose(fp);
084: 
085:   // DEBUG
086:   //for(i=0; i<NALPHA; ++i)
087:     //printf("%c: %f\n", 'a'+i, f[i]);
088: 
089: }
090: 
091: char estrai_lettera(const double f[])
092: {
093:   double n_casuale = rand() / (double) RAND_MAX; // numero a caso tra 0 e 1 (inclusi)
094:   int i;
095: 
096:   for(i=1; i<NALPHA; ++i) // vedo dove si piazza il percentile estratto a caso
097:     if(n_casuale<=f[i]) 
098:       return 'a' + i; // mi permette di calcolare il codice ascii corrispondente
099: 
100:   // FIXME qui non devo MAI arrivare
101:   printf("ERRORE in estrai_lettera()!!!!\n");
102:   return -1;
103: }
104: 
105: int verifica_parola(char lettere[], const char parola[])
106: {
107:   // l'idea e' quella di analizzare la parola lettera per lettera e verificare se le lettere sono presenti nell'altro array. Man mano che le trovo le "cancello" dall'altro array
108: 
109:   int ii , jj, ntrovate=0;
110:   for(ii=0; ii<strlen(parola); ++ii) // ciclo per tutte le lettere della parola
111:   {
112:     for(jj=0; jj<strlen(lettere); ++jj) // ogni lettera della parola la cerco nell'altro array
113:     {
114:       if(parola[ii] == lettere[jj]) // l'ho trovata tra le lettere valide
115:       {
116:   lettere[jj]='*'; // cancello la relativa lettera perche' le posso usare una e una sola volta
117:   ++ntrovate; // conto quante lettere ho trovato
118:   break; // termino il ciclo interno visto che ho trovato la lettera
119:       }
120:     }
121:   }
122: 
123:   // verifico che il numero di lettere trovate coincida con il numero di lettere della parola
124:   // se non e' cosi', qualche lettera evidentemente non c'era
125:   if(ntrovate==strlen(parola)) return 1;
126:   else return 0;
127: 
128: } // considerazione su questa funzione: non e' bellissima visto che modificas l'array lettere e non e' indice di buonissima programmazione. In questo caso ha senso, ma in una ottica piu' generale sarebbe stato bene usare una copia di lettere
129: 
130: int verifica_dizionario(const char parola[]){
131: 
132:   char tmp[100]; // temporaneo per memorizzare parola letta
133: 
134:   FILE *fp=fopen("dizionario.txt", "r"); // apro relativo file in lettura
135:   if(!fp)
136:   {
137:     perror("");
138:     exit(EXIT_FAILURE);
139:   }
140: 
141:   int confronto=1;
142:   while(fscanf(fp, " %s", tmp)==1) // leggo parola per parola
143:   {
144:     confronto = strcmp(parola, tmp);
145: 
146:     if(!confronto || confronto < 0 ){ // esco dal ciclo se trovo la parola (confronto=0) oppure se sono arrivato oltre in ordine alfabetico (confronto<0). Bastava if(confronto<=0)
147:       //printf("La parola in cui fermo la ricerca e' %s\n", tmp); // DEBUG
148:       break;
149:     }
150: 
151:   }
152:   fclose(fp);
153: 
154:   return !confronto; // uso il NOT logico per restituire VERO se l'ho trovata
155: 
156: }
157: 
158: