Do you need any help?

Come velocizzare "traduzione" dei versi?

P
PaoloT (2030 points)
3 11 17
asked Nov 18, 2020 in HW4 obbligatorio by PaoloT (2,030 points)
Sono arrivato al punto in cui il mio ultimo problema è dover aumentare l'efficienza del programma perché ci sono 5 test che non passano il timeout. Per il test più lento il programma impiega circa 30 ms in più sopra la soglia dei 100 del timeout e dal profiler ho notato che il problema principale sembra essere che la funzione con cui "traduco" il file di test.

Ciò che faccio è aprire il file di testo con encoding utf-8, creare una lista vuota, usare un for per scorrere tutti i versi e poi uso replace per gli spazi, lower per le maiuscole, e maketrans e translate per gli accenti e i simboli. Poi inserisco ogni verso nella lista e ricomincio il ciclo.

C'è qualcosa che posso fare per ottimizzare? O magari qualche consiglio generale per far sì che il test non vada in timeout? Ho provato a mettere come condizione verso.isalnum() e togliere i caratteri non alfanumerici ed ho notato che era davvero efficiente ma purtroppo gli accenti rimangono.

3 Answers

Best answer
Francesco.Danese (2130 points)
0 1 9
answered Nov 18, 2020 by Francesco.Danese (2,130 points)
selected Nov 18, 2020 by PaoloT

Ciao, la soluzione più adatta, semplice e veloce consiste nell'usare solamente la funzione Translate e MakeTrans. Con translate puoi, nello stesso momento, senza alcun for/replace/lower cambiare tutto il testo in lettere minuscole non accentate e allo stesso tempo anche eliminare dei caratteri a tua scelta (nel caso dell 'hw bisogna eliminare lo spazio " " , e i seguenti chars: ? , . ; : ' !

Qui trovi delle informazioni utili, ma puoi cercare come funziona translate altrove o dove trovi più comprensibile. 

Se continuerai ad avere difficoltà nel comprendere il suo funzionamento rispondi pure qua sotto, sarò lieto di aiutarti ;)

P
PaoloT (2030 points)
3 11 17
commented Nov 18, 2020 by PaoloT (2,030 points)
edited Nov 18, 2020 by PaoloT
Ciao, grazie mille dei consigli! (ho letto anche il commento sopra), ho tolto il .replace() che avevo usato per gli spazi e adesso li tolgo col translate, però come faccio a cambiare tutto il testo in minuscole senza usare lower? Devo mettere ogni carattere maiuscolo assieme ai simboli? Inoltre che intendevi con salvare il testo in una variabile per non riutilizzare translate dopo? Per adesso la funzione che uso ritorna la lista dei versi tradotti e se non sbaglio le variabili globali sono vietate.

Comunque avendo usato translate sul testo prima di splittarlo in righe e aver tolto il replace sono passato da 5 test non passati a 2, per caso hai idea di cos'altro posso fare oltre a cercare di togliere il lower()?
Francesco.Danese (2130 points)
0 1 9
commented Nov 18, 2020 by Francesco.Danese (2,130 points)
Allora come ormai saprai Translate cambia ogni occorrenza di un carattere nel suo corrispondente, e la corrispondenza è data dal 'mappaggio' (maketrans) usato. Dunque così come ogni qual volta che incontra à á â ã le cambia in a a a a puoi fare la stessa cosa con le maiuscole, da ABCD...  abcd.... etc etc. Ricapitolando, nel tuo maketrans dovrebbero esserci tutte le vocali accentate e tutte le lettere maiuscole, corrispondenti a tutte le vocali non accentate e tutte le lettere minuscole ( del tipo (àèòAEOBX, aeoaeobx)). E come terzo argument i caratteri speciali da eliminare (più lo spazio " " ). Ti consiglio comunque di sperimentare usando l'idle o la console.

Per quanto riguarda quando usare il translate ti consiglio di farlo una sola volta all'inizio della tua funzione ex1, dopo aver importato il file, e salvi il testo tradotto ( volendo anche splittato ) in una variabile, del tipo: testo_senza_accenti_ne_maiuscole = poesia.transalte... etc etc .

Così ogni volta che dovrai usarlo in altre funzioni ti basterà chiamare la funzione che vuoi eseguire dentro ex1 passandogli fra i parametri la tua variabile corrispondente al testo tradotto.

;)
P
PaoloT (2030 points)
3 11 17
commented Nov 18, 2020 by PaoloT (2,030 points)
edited Nov 18, 2020 by PaoloT
Grazie mille, mi sei stato molto d'aiuto!
Ho appena fatto le ultime modifiche e ricaricato il test e ora prendo persino il bonus d'efficienza, grazie davvero!
AdSum (16290 points)
9 20 134
answered Nov 18, 2020 by AdSum (16,290 points)
Purtroppo la conversione del testo prende il tempo che deve prendere essendo testi corposi (penso che praticamente a tutti sia una delle parti più pesanti), l'unica cosa che puoi fare è ottimizzare il resto del codice in modo da rientrare nei tempi, che sulla conversione puoi fare veramente poco.
P
PaoloT (2030 points)
3 11 17
commented Nov 18, 2020 by PaoloT (2,030 points)
Solo la conversione però impiega 80ms, è possibile o sto sbagliando qualcosa? La conversione la richiamo anche per calcolarmi il numero di ES nei versi e gli ES finali, farlo aumenta di molto il tempo? E se sì posso evitare di farlo?
Francesco.Danese (2130 points)
0 1 9
commented Nov 18, 2020 by Francesco.Danese (2,130 points)
reshown Nov 18, 2020 by Francesco.Danese
Ho già risposto qua sotto, ma leggendo il tuo commento cercherò di essere più chiaro.

Ti conviene inanzitutto tradurre l'intero file prima di dividerlo in versi.

Usando translate puoi rendere minuscole tutte le lettere, sostituire le vocali accentate con le non accentate ed elminare i caratteri speciali e gli spazi.

Una volta fatto salva il testo tradotto in una variabile e utilizza sempre quella per i tuoi calcoli, in questo modo translate verrà utilizzato una sola volta all'inizio.
m
marco.soda (470 points)
0 0 3
answered Nov 18, 2020 by marco.soda (470 points)
Fai attenzione sul modo in cui la funzione riconosce le lettere da scartare. Prova a definire subito i range di caratteri che devono essere "eliminati" o che comunque non devono essere sostituiti in modo tale da fare i controlli solo sulle lettere accentate per esempio.