Salta al contenuto
Note per Studenti Esercizio 2 · leggere il codice, cicli e valori restituiti

Esercizio 2leggere il codice, cicli e valori restituiti

Esame
In questa pagina 3

Testo (questionari di novembre e dicembre 2022 e test d'esame di gennaio 2014 del corso di Fondamenti di Informatica UniPD; adattato da un tema d'esame in Java, qui riscritto in Python). Per ciascun frammento dire che cosa restituisce o stampa, senza eseguirlo, poi verificare. Teoria: Ciclo whileCiclo while, cicli controllati da contatore, da sentinella e da condizione; break, continue, else; terminazione e invariante di ciclo.Ciclo while →, Ciclo for e rangefor scorre gli elementi di un iterabile; range per gli indici; enumerate, zip, reversed, sorted; cicli annidati; quando usare for e quando while.Ciclo for e range →, Funzioni in Pythondef e return, parametri posizionali, con nome e con valore predefinito, *args e **kwargs; passaggio per riferimento a oggetto; ambito delle variabili LEGB; docstring, type hint, lambda.Funzioni in Python →.

python
def f1(r, s):               # (a) con r > 0
    q = 1
    i = 0
    while i < r:
        q *= s
        i += 1
    return q

def f2(r, s):               # (b) con r > 0, e (c) con r < 0
    q = 0
    i = 0
    while i < r:
        q += s
        i += 1
    return q

def minimo(b):              # (d) b non vuota
    c = b[0]
    i = 1
    while i < len(b):
        if b[i] < c:
            c = b[i]
        i += 1
    return c

def f3(n):                  # (e) con n > 0, e (f) con n < 0
    k = n
    for i in range(n - 1, 0, -1):
        k = k * i
    return k

def copia_troncata(b, c):   # (g)
    n = min(c, len(b))
    d = [None] * c
    d[:n] = b[:n]
    return d

j, i = 0, 10                # (h)
while i > 4:
    j += 1
    i -= 1
print("il ciclo è stato eseguito", j, "volte")

Metodo

Per ogni frammento si costruisce una tabella di traccia: una riga per ogni controllo della condizione del ciclo, una colonna per ogni variabile. Si aggiorna riga per riga a mano, senza anticipare il risultato.

(a) f1(r, s), r>0r > 0

Tracia con r=3r = 3, s=2s = 2:

controllo i < r i q
inizio 0 1
0<30 < 3 vero → corpo 1 2
1<31 < 3 vero → corpo 2 4
2<32 < 3 vero → corpo 3 8
3<33 < 3 falso → esce

q parte da 11 e viene moltiplicato rr volte per ss: restituisce srs^r (=8= 8). Non r⋅sr\cdot s (somma ripetuta) e non un ciclo infinito: i cresce sempre fino a rr.

(b) f2(r, s), r>0r > 0

Stessa struttura, ma q parte da 00 e si somma ss per rr volte: restituisce r⋅sr\cdot s (con r=3r=3, s=2s=2: 0,2,4,60,2,4,6).

(c) f2(r, s), r<0r < 0

La condizione i < r con i=0i = 0 e r<0r < 0 è falsa subito: il corpo non viene mai eseguito e la funzione restituisce il valore iniziale, 0. Un ciclo while può non eseguirsi mai (a differenza del do ... while di altri linguaggi).

(d) minimo(b)

c è il minimo dei primi elementi esaminati: ad ogni passo, se b[i] è più piccolo, lo sostituisce. Restituisce l'elemento minimo. Con b = [4, 7, 2, 9]: c=4,4,2,2c = 4, 4, 2, 2.

(e) f3(n), n>0n > 0

k parte da nn e i scorre n−1,n−2,…,1n-1, n-2, \dots, 1: k=n⋅(n−1)⋯1=n!k = n\cdot(n-1)\cdots 1 = n!. Il terzo argomento di range è il passo (−1-1).

(f) f3(n), n<0n < 0

range(n - 1, 0, -1) con n−1<0n-1 < 0 è vuoto (si scende da un numero negativo verso 00, ma la condizione di arresto è già superata): il corpo non gira e restituisce k = n stesso.

(g) copia_troncata(b, c)

Crea una nuova lista di lunghezza c (con None nei posti non riempiti) e vi copia i primi min(c, len(b)) elementi di b. Non modifica b: non "ridimensiona" la lista ricevuta, ne restituisce una nuova (per questo, di solito, si usa b = copia_troncata(b, c)).

(h) Contare le iterazioni

i assume i valori 10,9,8,7,6,510, 9, 8, 7, 6, 5 mentre la condizione i > 4 è vera; con i=4i = 4 si esce. Sono 10−4=610 - 4 = 6 iterazioni: stampa "il ciclo è stato eseguito 6 volte".

Verifica

python
assert f1(3, 2) == 8 and f1(0, 5) == 1
assert f2(3, 2) == 6 and f2(-3, 2) == 0
assert minimo([4, 7, 2, 9]) == 2
assert f3(5) == 120 and f3(-3) == -3 and f3(1) == 1
assert copia_troncata([1, 2, 3], 5) == [1, 2, 3, None, None]
assert copia_troncata([1, 2, 3], 2) == [1, 2]
print("tutto confermato")

Errori comuni

  • Eseguire mentalmente "a occhio" e indovinare la formula: la tabella di traccia evita di confondere srs^r con r⋅sr\cdot s.
  • Dimenticare che, se la condizione è subito falsa, il ciclo non gira e si restituisce il valore iniziale.
  • Con range(a, b, passo): il passo negativo richiede a>ba > b, altrimenti l'intervallo è vuoto; l'estremo bb è escluso.
  • Contare le iterazioni con un errore di uno (i > 4 e i >= 4 differiscono di una iterazione).

Versione ripasso

Questionari di novembre e dicembre 2022 e test di gennaio 2014 (Fondamenti di Informatica, UniPD; adattato da Java a Python). Si usa una tabella di traccia: una riga per controllo della condizione, una colonna per variabile. Teoria: Ciclo whileCiclo while, cicli controllati da contatore, da sentinella e da condizione; break, continue, else; terminazione e invariante di ciclo.Ciclo while →, Ciclo for e rangefor scorre gli elementi di un iterabile; range per gli indici; enumerate, zip, reversed, sorted; cicli annidati; quando usare for e quando while.Ciclo for e range →.

  • q = 1; while i < r: q *= s → srs^r (con r=3r = 3, s=2s = 2: q=1,2,4,8q = 1, 2, 4, 8).
  • q = 0; while i < r: q += s → r⋅sr\cdot s; con r<0r < 0 la condizione è subito falsa, il ciclo non gira e restituisce 0.
  • Minimo di una sequenza: c = b[0], if b[i] < c: c = b[i] → elemento minimo.
  • k = n; for i in range(n - 1, 0, -1): k *= i → n!n! per n>0n > 0; per n<0n < 0 il range è vuoto e restituisce n.
  • Copia troncata: lista nuova di lunghezza c, d[:n] = b[:n] con n = min(c, len(b)); b non cambia.
  • while i > 4 partendo da 10 con i -= 1: 6 iterazioni (i=10,…,5i = 10, \dots, 5).

Errori comuni: indovinare la formula senza tabella; dimenticare il ciclo che non gira; passo negativo con range vuoto; errore di uno.

Teoria collegata