Python, Memoria e While loops

prof. Matteo Lugli

Created: 2024-02-16 ven 19:46

Introduzione

Durante le ultime lezioni girando per i banchi mi sono annotato gli errori piu' frequenti che vengono commessi durante la risoluzione degli esercizi;

Oggi vediamo qualche esercizio ispirato a questi errori, per capire un po' meglio come funzionano alcune cose "cattivelle";

Esercizi di ripasso

Esercizio 1

l = (1,2,3,4,5)
l[1] = 14
print(l)

Cosa succede se eseguiamo questo codice?

Errore!

Le tuple sono simili alle liste, ma non potete modificarle una volta create.

Esercizio 2

l1 = [1,2,3,4,5]
l2 = l1
l1[0] = "X"
print(l1)
print(l2)

Cosa viene stampato?

['X', 2, 3, 4, 5]
['X', 2, 3, 4, 5]

??

Usando \(l2 = l1\) abbiamo creato un altro puntatore allo stesso oggetto in memoria.

Quindi accedere alla lista \([1,2,3,4,5]\) tramite \(l1\) o tramite \(l2\) e' la stessa cosa.

Per creare una copia della lista l1, e' necessario usare la direttiva .copy()

Esercizio 3

Vediamo un altro esercizio:

t1 = [[1,2,3], [1,2,3]]
t2 = t1.copy()
t2[0][1] = 23
print(t1)
print(t2)

Cosa viene stampato?

[[1, 23, 3], [1, 2, 3]]
[[1, 23, 3], [1, 2, 3]]

Il metodo copy() non funziona nel modo che tutti pensiamo…

copy() crea una nuova lista contenente i riferimenti agli oggetti della lista di partenza;

Morale della favola: quando avete lavorate con oggetti complessi (dizionari o liste innestate) usate il metodo deepcopy():

from copy import deepcopy
t1 = [[1,2,3], [1,2,3]]
t2 = deepcopy(t1)
t2[0][1] = 23
print(t1)
print(t2)
[[1, 2, 3], [1, 2, 3]]
[[1, 23, 3], [1, 2, 3]]

Cicli While

I cili while sono simili ai cicli for, con qualche piccola differenza;

x = 0
while x < 10:
        print(x)

Cosa viene stampato?

0
0
0
...

A differenza dei cicli for, nei cicli while la variabile di controllo non viene incrementata automaticamente.

La versione corretta del codice per stampare i numeri da 0 a 9 e' la seguente:

x = 0
while x < 10:
        print(x)
        x+=1

I cili while possono tornare utili:

Quando ci serve flessibilita' nell'aggiornamento della variabile di controllo;

Quando conosciamo la condizione di terminazione di un ciclo ma non sappiamo esattamente come iterare;

Per capire meglio l'utilita' dei while, vediamo un esercizio:

Esercizio while loop


Dato un valore \(n\) che sia una potenza del 2, stampare la seguente successione di valori: \([\frac{n}{2}, \frac{n}{4}, \frac{n}{8}, ..., 1]\)

Soluzione:

n = 64
while n > 1:
        n = n/2
        print(n)

AOC 2019 D1 P1, P2

La prima parte e' semplice (esercizio medium regalato da verifica), non serve usare i cicli while;

Nella seconda parte invece e' quasi obbligatorio;

Suggerimento


Per effettuare una divisione intera (scartando il resto), si usa l'operatore //;

Soluzione

  • Parte 1
    with open("test.txt") as f:
            values = f.read().splitlines()
            fuel = 0
            for value in values:
                    fuel += int(value) // 3 - 2
            print(fuel)
    
  • Parte 2
    with open("test.txt") as f:
            values = [int(x) for x in f.read().splitlines()]
            fuel = 0
            for value in values:
                    while value // 3 - 2 > 0:
                            value = value // 3 - 2
                            fuel += value
            print(fuel)