I “Promessi Sposi” dalla A alla Z in 36 caratteri – B-log(0) :B-log(0)
Per la serie informazioni indispensabili per blog indispensabili, oggi vi regalo una chicca che nessun altro sicuramente vi ha mai proposto: la risposta alla domanda “qual è il più breve pezzo di Promessi Sposi contenente tutte e 21 le lettere dell’alfabeto?“
Ve lo siete sempre chiesto, nevvero? (scusate il “nevvero”, ma Manzoni invoglia a usare parole desuete)
Ecco qua la risposta (in grassetto):
Allora Gertrude, che non l’avrebbe voluto a quella condizione, era costretta di tirarsi indietro, di rifiutar quasi i primi segni di benevolenza che aveva tanto desiderati, di rimettersi da sé al suo posto di scomunicata; e per di più, vi rimaneva con una certa apparenza del torto.
36 caratteri (alfabetici) per comprendere tutte le 21 lettere (escluse le 5 lettere straniere, ovviamente), con uno spreco assolutamente insopportabile di i, addirittura 6, che vergogna…
Dante sarà stato più attento?
Naturalmente la risposta la potete sapere solo qui su b-log(0), che ha l’assoluta esclusiva su questo scoop:
E ‘l buon maestro: «Questo cinghio sferza
la colpa de la invidia, e però sono
tratte d’amor le corde de la ferza.
43 caratteri? CLAMOROSO! Vince Manzoni per distacco!
Fermi tutti! Sono sicuro che passando alla Sacra Bibbia non ci saranno rivali, dalla dettatura di Dio mi aspetto una frase miracolosa che comprenda le 21 lettere in 20 caratteri o qualcosa del genere… ma invece, incredibilmente:
Saul, mentre guardava Davide uscire incontro al Filisteo, aveva chiesto ad Abner capo delle milizie: “Abner, di chi è figlio questo giovane?”.
40 caratteri e un chiaro tentativo di truccare le carte con un nome insensato come “Abner” buttano giù dal primo posto un Dio decisamente sottotono.
Quindi dichiaro Manzoni campione, ci tocca riprendere in mano i “Promessi Sposi” e rileggerli prestando maggiore attenzione!
(il tutto è nato da una “sfida” che mi ha lanciato un collega, così oggi ho perso un’oretta per fare un programma totalmente inutile ma che mi darà gloria eterna.)
ps: se vi interessa il codice C/C++, lo trovate qui sotto (senza colori è difficile da leggere, accontentiamoci…)
# include <iostream> # include <cstdlib> # include <fstream> # include <assert.h> using namespace std; # define MAX_VAL 100 # define A_ASCII_VAL 97 # define Z_ASCII_VAL 122 unsigned int charTable [26]; char memLine[MAX_VAL]; char bestLine[MAX_VAL]; unsigned int head, tail; unsigned int countedLetters; unsigned int minCounted = MAX_VAL; unsigned int foundLetters; char convertChar(char line); void findShorterLineAZ(string line); int main (int argc, char **argv) { unsigned int i; ifstream myfile("nomeTesto.txt"); if (myfile.is_open()) { // inizializzazione tabella dei caratteri trovati // (metto a 100 le lettere inglesi) for(i = 0; i < 26; i++) if (i == 9 or i == 10 or (i >= 22 and i <= 24)) charTable[i] = 100; charTable[i] = 0; countedLetters = foundLetters = 0; head = tail = 0; // ciclo il file fino alla fine while (! myfile.eof() ) { getline (myfile,line); // chiamo la funzione principale che stampa i risultati findShorterLineAZ(line); } myfile.close(); } else { cerr << "Errore nell'apertura del file" << endl; return EXIT_FAILURE; } return EXIT_SUCCESS; } void findShorterLineAZ(string line) { register unsigned int i, j; char mychar; unsigned int index; // ciclo tutta la linea, carattere per carattere for (i=0; i<line.size(); i++) { // metto tutto in minuscolo, converto gli accenti, // controllo che sia un valore alfabetico e salvo in mychar if (isalpha(mychar = convertChar(line[i]))) { // indice = valore ASCII della lettera meno valore ASCII della 'a' index = mychar-A_ASCII_VAL; } else { // lettera non valida, passo alla successiva continue; } // salvo in coda al buffer circolare memLine[tail++] = mychar; if (tail == MAX_VAL) tail = 0; // buffer pieno, head++ and ricontrollo la tabella if (tail == head) { if (--charTable[(memLine[head++] - A_ASCII_VAL)] == 0) foundLetters--; countedLetters--; } // coda e testa tornano all'inizio del buffer, se sono alla fine if (head == MAX_VAL) head = 0; // nuova lettera trovata if (charTable[index]++ == 0) foundLetters++; countedLetters++; // controllo che non si superi mai il max (per qualche errore) assert (countedLetters <= MAX_VAL); // trovate tutte e 21? if (foundLetters == 21) { // inizio a spostare avanti HEAD e accorcio la sequenza // il più possibile, aggiornando ogni volta la tabella while (--charTable[(memLine[head++] - A_ASCII_VAL)] != 0) { countedLetters--; if (head == MAX_VAL) head = 0; } if (head == MAX_VAL) head = 0; countedLetters--; // questa sequenza è la migliore al momento? if (countedLetters < minCounted) { // stampo a video l'attuale miglior soluzione for(int j = head-1, k = 0; k <= countedLetters; j++, k++) { printf("%c", memLine[j]); if (j == MAX_VAL-1) j = 0; } minCounted = countedLetters; } foundLetters--; } } } char convertChar(char line) { // se la lettera è alfabetica, metto in minuscolo if (isalpha(line)) return tolower(line); // se è uno spazio o altro, return if (isblank(line)) return line; // se è un accento, lo converto nella rispettiva lettera senza accenti if (line == -24 or line == -23) return 'e'; if (line == -32) return 'a'; if (line == -7) return 'u'; if (line == -20) return 'i'; if (line == -14) return 'o'; return line; }