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: