Suggerimenti [1d5] SE la prima lettera della matrice (in alto a sinistra, matrice[0,0]) è diversa dalla prima lettera della parola (parola[0]) ALLORA siamo già sicuri di non poter individuare la parola nella matrice
Suggerimenti [2d5] SE (parola[0]==matrice[0,0]) ALLORA il problema si riduce a verificare se il resto della parola è individuabile a partire da matrice[0,1] (ricerca verso destra), OPPURE da matrice[1,0] (ricerca verso il basso)
Suggerimenti [3d5] SE la parola è lunga un solo carattere ALLORA il problema diventa molto semplice
Suggerimenti [4d5] OVVIAMENTE, Nell'esplorare la matrice dobbiamo porre la massima cautela nel non superare le colonne d'Ercole, dato che la matrice possiede un numero finito di righe e di colonne
Suggerimenti [5d5] Dicotomia: Iterazione Vs. Ricorsione Un approccio iterativo potrebbe Esplorare la matrice muovendo due indici [r,c] Tenere traccia delle porzioni di parola individuate Marcare le posizioni che non possono costituire soluzione, o che pur potendo non la costituiscono Fare backtrack quando necessario Sì ma.. la ricorsione si offre di gestire per noi, e gratis, il meccanismo di nesting/backtracking!
L'Algoritmo [1d5] Si tratta di una funzione ricorsiva, il cui prototipo minimo può essere qualcosa di simile al seguente string f (int r, int c, string p, string o) L'idea è che la funzione restituisca una stringa che descrive il cammino che dalla posizione [r,c] individua la parola p, considerando che si è già svolto un certo cammino o per arrivare in posizione [r,c]
L'Algoritmo [2d5] string f (int r, int c, string p, string o) r: indice della riga in cui iniziare la ricerca c: indice della colonna in cui iniziare la ricerca p: parola da ricercare o: cammino parziale percorso fino a quel momento per giungere in posizione [r,c]
L'Algoritmo [3d5] La prima chiamata f(0, 0, parola, “”) Una chiamata ricorsiva “destra” f(r, c+1, parola+1, [?]) Una chiamata ricorsiva “basso” f(r+1, c, parola+1, [?]).. E questo misterioso quarto parametro?
L'Algoritmo [4d5] Il quarto parametro è il cammino (dentro la matrice) che via via costruiamo, e che alla fine costituirà l'output del problema L'idea è che ad ogni chiamata della funzione f le venga passato il cammino attuale inteso come testimonianza del come si è giunti al punto [r,c]
L'Algoritmo [5d5] La funzione valuterà se da quel punto una soluzione è impossibile (e in caso restituirà il valore ASSENTE), altrimenti arricchirà il cammino passato della mossa del caso, e restituirà il tutto come risultato della funzione Il susseguirsi delle chiamate ricorsive nell'inevitabilmente giusto ordine costruirà il cammino (se il cammino esiste, altrimenti sarà restituito ASSENTE)
I dettagli [1d4] In pieno spirito OII non eseguiamo alcun controllo di validità sui dati di ingresso semplicemente, assumiamo siano corretti ;-)
I dettagli [2d4] Si noti che dal file di input leggiamo stringhe di testo (riga per riga), che però poi disponiamo in una matrice quadrata di caratteri
I dettagli [3d4] Abbiamo scelto di utilizzare la “A” come carattere di output, oltre a “D” (destra) e “B” (basso) “A” sta per “assente”, e ricevere dalla funzione f una “A” come esito indica che quella sottoricerca è fallita
I dettagli [4d4] Estendiamo la libreria di input/output string leggiStringa(void) { string x; in >> x; return x; } void scriviStringa(string x) { out << x; }