Velocizzare il codice

M
Mic_s (670 points)
2 16 22
asked Nov 3, 2020 in HW2 obbligatorio by Mic_s (670 points)
Salve, ho ancora problemi con l'hw2, nonostante abbia cercato di seguire i consigli del peer assessment. Con il timeout il codice non mi passa gli ultimi 4 test, senza si. Penso che il problema più grande sia che il programma è troppo lento quando scorre le lettere, o le parole di ogni giocatore per calcolarne il punteggio. Ho fatto una funzione ausiliare che appunto calcola il punteggio utilizzando diversi for per far scorrere le parole e contemporaneamente i punteggi dal dictionary. Purtroppo non riesco ad ottimizzare questa parte, come posso fare?

Grazie in anticipo per le risposte.
358 views

3 Answers

Best answer
s
stefano.fantauzzi (2260 points)
3 6 17
answered Nov 3, 2020 by stefano.fantauzzi (2,260 points)
selected Nov 3, 2020 by Mic_s
Primo consiglio universale per migliorare l'efficienza:  calcola il punteggio di ogni giocatore (a cui sottrarrai le penalità) un'unica volta considerando come unica parola la concatenazione delle parole giocate. Questo ti permette di evitare il calcolo e conseguente aggiornamento del punteggio ad ogni turno. Per farlo in maniera intelligente ovviamente considera il metodo join applicato alla lista delle giocate di ogni giocatore. Infine ti lascio uno spunto su cui riflettere: esiste un metodo delle stringhe chiamato translate, e puoi applicare il metodo sum alla stringa numerica tradotta, a patto di codificarla. Spero di esserti stato utile!
M
Mic_s (670 points)
2 16 22
commented Nov 3, 2020 by Mic_s (670 points)
Grazie, non avevo pensato all'unione di tutte le parole in un'unica stringa ed effettivamente ha diminuito il tempo. Non ho ben capito a cosa serve il metodo translate.

ho verificato ora e grazie a questa piccola modifica ho passato un test in più quindi grazie mille!
s
stefano.fantauzzi (2260 points)
3 6 17
commented Nov 3, 2020 by stefano.fantauzzi (2,260 points)

Ultimo consiglio cheeky: il metodo translate ti permette, se hai un dizionario, di sostituire in un colpo ogni carattere della stringa presente come chiave nel dizionario con il suo valore. A questo punto puoi codificare la stringa e invocare il metodo sum per calcolare il punteggio! Ti consiglio di leggere la documentazione del translate per saperne di più wink

cini.1933403 (660 points)
2 7 12
commented Nov 3, 2020 by cini.1933403 (660 points)
Ma per usare sum poi devi spezzare i numeri tra di loro o sbaglio? Se hai una sequenza ininterrotta di n cifre, non ti fa la somma tra queste.
MRinaudo (3660 points)
18 40 50
commented Nov 3, 2020 by MRinaudo (3,660 points)

stefano.fantauzzi 

Applicando il tuo ragionamento, sono riuscito a passare tutti i test (mentre prima non passavo gli ultimi due).

Grazie mille!  laughyes

M
Mic_s (670 points)
2 16 22
commented Nov 3, 2020 by Mic_s (670 points)
Grazie mille, ora mi passa tutti i test!
M
MatteoB (1690 points)
8 16 21
commented Nov 4, 2020 by MatteoB (1,690 points)
io ho provato ad usare questo metodo ma non funziona

prendo come esempio la parola "ciao"

poi provo a stampare la parola.translate(mioDizionario), dove mioDiozionario prendo come riferimento quelle HW.

Quando stampo mi rida la stessa stringa, cioè "ciao"
MRinaudo (3660 points)
18 40 50
commented Nov 4, 2020 by MRinaudo (3,660 points)

Ciao MatteoB 

non devi per forza usare il metodo translate.

Potresti mettere le lettere, per ogni giocatore, tutte insieme in varibili diverse. Poi, una sola volta e per ciascun giocatore, verifichi se ogni lettera è presente nel tuo dizionario, e aggiungi i punti in base al valore di ogni chiave.

Spero di esserti stato d'aiuto smiley

M
MatteoB (1690 points)
8 16 21
commented Nov 5, 2020 by MatteoB (1,690 points)
Ti spiego perchè ho una funzione che (è quella che mi porta via più tempo) mi scorre la parola che mi splitto

e in una variabile di appoggio mi memorizzo, facendomi riportare il valore di quella chiave ad esempio se incontro il carattere 'e', dal dizionario mi vado a prendere il valore corrispondente e poi man mano lo sommo.

Non saprei proprio come ottimizzare questa funzione
giordano_sannino (13650 points)
7 16 81
answered Nov 3, 2020 by giordano_sannino (13,650 points)
"scorrere parole e contemporaneamente i punteggi dai dizionari"

Cioè? Scorri una volta per i punteggi e una volta per usare il dizionario? Se si magari modificherei, ma forse ti sei soltanto spiegato male
M
Mic_s (670 points)
2 16 22
commented Nov 3, 2020 by Mic_s (670 points)
Praticamente quello che faccio è:

creare un ciclo for per scorrere tutte le lettere nel dictionary

  creare un for che scorra ogni parola nella lista

    un for che scorra tutte le lettere nella parola

      un if che mi verifica se la lettera dal dictionary è la stessa di quella nella parola
C
ChristianSt (1790 points)
3 9 25
commented Nov 3, 2020 by ChristianSt (1,790 points)
Non ti serve lo scorrimento basta che fai dizionario[lettera] e ti ritorna il valore
M
Mic_s (670 points)
2 16 22
commented Nov 3, 2020 by Mic_s (670 points)
Si faccio così, lo scorrimento lo uso per verificare quale lettera del dictionary si trova nella parola e poi la utilizzo come key per sommare il valore
C
ColellaV (1040 points)
2 3 9
commented Nov 3, 2020 by ColellaV (1,040 points)

Non ti conviene partire dal dizionario e cercare la corrispondenza nella parola, basta che, in pseudocodice, fai:

PER OGNI lettera IN parola

    punti_lettera = dizionario[lettera]

Posto che tu abbia un dizionario del tipo {a:1, b:3, c:3, ... , z:10}

cini.1933403 (660 points)
2 7 12
answered Nov 3, 2020 by cini.1933403 (660 points)
edited Nov 3, 2020 by cini.1933403

Puoi usare il profiler e mettere @profile prima di ogni funzione per vedere quanto tempo impiegano e capire cosa sta rallentando il tuo codice

Qui ci sono le istruzioni [nella tabella è spyder-line-profiler]:  Istruzioni Q2a
Qui dei suggerimenti del prof.Sterbini a riguardo: Trick

Quando capisci cosa è lento torna qua.

Dimenticavo: per far partire il profiler, dopo che hai messo il decoratore, devi premere shit+f10; se sei su un laptop probabilmente devi premere anche il tasto Fn

M
Mic_s (670 points)
2 16 22
commented Nov 3, 2020 by Mic_s (670 points)
Ho fatto e come dicevo la funzione che utilizzo per calcolare i punti di ogni giocatore è quella che impiega il maggior tempo
cini.1933403 (660 points)
2 7 12
commented Nov 3, 2020 by cini.1933403 (660 points)

Leggevo la risposta sopra ma mi sembra molto complesso quello che hai fatto: è ok che scorri le parole e poi scorri le lettere della parola, ma se hai creato il dizionario con tutte le lettere da A-Z non dovresti controllare se la lettera è presente in quanto penso l'hai già scritta; se invece hai creato un dizionario con molteplici lettere come valore di una singola chiave, e poi vai a cercare se è li dentro stai vanificando il tutto, era stato anche testato qualche lezione fa... dovresti semplicemente dare la key al dizionario e farti ritornare il valore corrispondente. Per il funzionamento del dizionario puoi vedere il testo consigliato [Think in python] nel capitolo dei dizionari (pg 127 in ita) [Download].

Quello che potrei consigliarti è su un nuovo file di creare una funzione dove passando le lettere di una parola ad un dizionario riesci a printarti quello che vuoi, così intanto ti fai dei test di funzionamento e probabilmente capisci come scriverlo nell'hw.

M
Mic_s (670 points)
2 16 22
commented Nov 3, 2020 by Mic_s (670 points)
Controllo se nella parola è presente una lettera che usata come key mi da il valore del punteggio