Esercizio - Python di base - input, liste, dizionari e funzioni (laboratorio 1)
In questa pagina 8
Otto esercizi del laboratorio 1 (introduzione a Python), con le soluzioni del corso di Intelligenza Artificiale, Ing. dell'Informazione UniPD. Servono per prendere confidenza con gli strumenti usati nei laboratori successivi: input, liste, dizionari, stringhe, funzioni, NumPy. Gli argomenti sono spiegati in Input e output da consoleinput() restituisce sempre una stringa da convertire; lettura di più valori su una riga; print con sep, end e file; flussi standard stdin, stdout, stderr e reindirizzamento.Input e output da console →, Liste in Pythonlist come sequenza mutabile (array dinamico); indici, slicing e assegnamento a fette; metodi e loro costo; aliasing, copia superficiale e profonda; list comprehension; liste annidate e matrici.Liste in Python →, Dizionari e insiemi in PythonADT mappa e insieme; dict con chiavi hashable, accesso, get, iterazione, conteggi e raggruppamenti; set e operazioni insiemistiche; tabelle hash e costo O(1) medio; Counter e defaultdict.Dizionari e insiemi in Python →, 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 →, Stringhe in Pythonstr come sequenza immutabile di caratteri Unicode; indici e slicing; operatori; metodi principali (split, join, strip, find, replace...); f-string e formattazione; confronto lessicografico.Stringhe in Python → e 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 →.
Un'avvertenza sull'input: restituisce sempre una stringa, anche se l'utente scrive 4. Le soluzioni del corso la convertono con eval, che valuta qualunque espressione Python scritta dall'utente (anche __import__('os')...): per leggere un numero è meglio float() o int(), che rifiutano tutto il resto con un errore. Qui si usa float.
Esercizio 1 - perimetro e area di un rettangolo
Testo. Scrivere un programma che chiede all'utente base e altezza di un rettangolo e stampa il valore del perimetro e dell'area.
Soluzione. Due funzioni pure, compute_perimeter(b, h) e compute_area(b, h), e il programma principale che legge, converte, chiama e stampa. Perimetro , area .
def compute_perimeter(b, h):
return 2 * b + 2 * h
def compute_area(b, h):
return b * h
base = float(input('Type the base of the rectangle: '))
height = float(input('Type the height of the rectangle: '))
print('Perimeter: ' + str(compute_perimeter(base, height)))
print('Area: ' + str(compute_area(base, height)))Con base 4 e altezza 4 si ottiene Perimeter: 16.0 e Area: 16.0 (la soluzione del corso con eval stampa 16, perché eval('4') è un intero; con float i valori sono sempre in virgola mobile). Con base 5 e altezza 3,5: perimetro , area .
Esercizio 2 - tipo, lunghezza, primo e ultimo carattere
Testo. Dopo s = input("What is your name? "), stampare il tipo della variabile s, la sua lunghezza, il primo e l'ultimo carattere.
Soluzione. type(s) dà sempre <class 'str'>; len(s) la lunghezza; s[0] il primo carattere; l'ultimo si ottiene con l'indice negativo s[-1], o equivalentemente s[len(s) - 1]. Se s è vuota gli indici sollevano IndexError.
s = input("What is your name? ")
print(type(s)) # <class 'str'>
print(len(s))
print(s[0])
print(s[-1])Con Maria: <class 'str'>, 5, M, a.
Esercizio 3 - somma troppo grande
Testo. Scrivere un programma che chiede due numeri. Se la somma dei due numeri supera 100, stampare "Number too large".
Soluzione. Si leggono i due valori, si converte, si calcola la somma e si controlla la condizione con if: la somma deve essere maggiore di 100 (strettamente).
x = float(input('Insert value x: '))
y = float(input('Insert value y: '))
if x + y > 100:
print('Number too large')Prove: stampa il messaggio; non lo stampa (100 non "supera" 100); lo stampa.
Esercizio 4 - minimo e massimo di una lista
Testo. Riempire una lista inizialmente vuota con 10 valori letti da tastiera. Stampare il valore più grande e il più piccolo contenuti nella lista.
Soluzione del corso: si parte da una lista vuota, si legge in un ciclo for i in range(10) e si fa L.append(n); poi si scandisce la lista tenendo un massimo e un minimo provvisori, inizializzati con L[0].
L = []
for i in range(10):
L.append(float(input('Type the number: ')))
massimo = L[0]
minimo = L[0]
for e in L:
if e > massimo:
massimo = e
if e < minimo:
minimo = e
print(L)
print(minimo)
print(massimo)Nella soluzione del corso le variabili si chiamano max e min, cioè come le funzioni predefinite: funziona, ma le nasconde (da quel punto max(L) non è più una funzione e dà un errore), quindi qui sono massimo e minimo. Con le funzioni predefinite basta print(min(L), max(L)). Con la lista il minimo è e il massimo è .
Esercizio 5 - numeri sopra la media con NumPy
Testo. Dopo aver importato il modulo numpy, creare un array di 100 numeri casuali con valori interi tra 0 e 50. Stampare tutti i numeri maggiori della media e la loro posizione. (Suggerimenti nella documentazione.)
Soluzione. np.random.randint(0, 50, size=100) crea 100 interi. Attenzione: l'estremo superiore è escluso, quindi i valori sono in ; per includere il 50 si scrive randint(0, 51, ...). La media è v.mean() (equivalente a np.mean(v) o np.average(v)). La condizione v > m dà un array di booleani, e np.nonzero ne restituisce gli indici.
import numpy as np
v = np.random.randint(0, 50, size=100)
m = v.mean()
print(v, m)
for i in range(100):
if v[i] > m:
print("Item:\t" + str(v[i]) + " in position:\t" + str(i))
# versione vettoriale
indici = np.nonzero(v > m)[0]
print(indici, v[indici])Con np.random.seed(0) prima della creazione si ottiene un array con media e 48 elementi sopra la media, i primi nelle posizioni con valori (i numeri dipendono dal seme; senza seme cambiano a ogni esecuzione).
Esercizio 6 - prodotto degli elementi di una lista
Testo. Scrivere una funzione multiplier_function(number_list) che, data una lista di numeri, moltiplica tra loro tutti gli elementi della lista e restituisce il risultato. Se la lista è vuota restituisce 0.
Soluzione. Il prodotto parte da 1 (elemento neutro); la lista vuota va gestita prima, perché altrimenti il prodotto vuoto darebbe 1 invece del 0 richiesto.
def multiplier_function(L):
if len(L) == 0:
return 0
product = 1
for e in L:
product *= e
return product
print(multiplier_function([1, 2, 3, 4])) # 24
print(multiplier_function([])) # 0
print(multiplier_function([5])) # 5Esercizio 7 - countdown
Testo. Scrivere una funzione countdown(string) che prende una stringa e restituisce la stringa rovesciata, con tutti i caratteri minuscoli e solo l'ultimo in maiuscolo (per esempio "abcd" diventa "dcbA"). Gestire anche la stringa vuota.
Soluzione. s[::-1] rovescia (passo ). L'ultimo carattere del risultato è tmp[-1], il resto tmp[:-1]; si mette il resto in minuscolo e l'ultimo in maiuscolo. La stringa vuota si restituisce subito, perché tmp[-1] darebbe IndexError.
def countdown(s):
if len(s) == 0:
return s
tmp = s[::-1]
return tmp[:-1].lower() + tmp[-1].upper()
print(repr(countdown(""))) # ''
print(countdown("abcd")) # dcbA
print(countdown("PyThOn")) # nohtyP
print(countdown("a")) # APer "abcd": rovesciata "dcba", resto "dcb" minuscolo, ultimo "a" maiuscolo "A", risultato "dcbA".
Esercizio 8 - frequenza dei caratteri
Testo. Scrivere una funzione frequency(string) che prende una stringa e restituisce un dizionario con la frequenza di ogni carattere. Per esempio, per "ababcc" restituisce {"a": 2, "b": 2, "c": 2}.
Soluzione. Si scandisce la stringa e per ogni carattere si incrementa il suo contatore; se la chiave non c'è ancora, parte da 0. La soluzione del corso usa if c in D: ... else: ...; D.get(c, 0) + 1 fa lo stesso in una riga.
def frequency(s):
D = {}
for c in s:
D[c] = D.get(c, 0) + 1
return D
print(frequency("ababcc")) # {'a': 2, 'b': 2, 'c': 2}
print(frequency("")) # {}La libreria standard ha già collections.Counter("ababcc"), che dà lo stesso risultato (è usato nel laboratorio 3, vedi Esercizio - Materiale supplementare di ricerca in Python - multimap, zip, slicing e Counter (laboratorio 3)).
Versione ripasso
inputdà sempre una stringa: si converte confloat()oint();evalesegue qualunque espressione e va evitato (Input e output da consoleinput() restituisce sempre una stringa da convertire; lettura di più valori su una riga; print con sep, end e file; flussi standard stdin, stdout, stderr e reindirizzamento.Input e output da console →).- Es. 1:
compute_perimeter(b, h) = 2*b + 2*h,compute_area(b, h) = b*h; base 4, altezza 4:16.0e16.0; base 5, altezza 3,5:17.0e17.5. - Es. 2:
type(s)è<class 'str'>,len(s),s[0],s[-1](os[len(s)-1]);Maria: 5,M,a; stringa vuota:IndexError(Stringhe in Pythonstr come sequenza immutabile di caratteri Unicode; indici e slicing; operatori; metodi principali (split, join, strip, find, replace...); f-string e formattazione; confronto lessicografico.Stringhe in Python →). - Es. 3:
if x + y > 100: print('Number too large'); strettamente maggiore: non stampa, sì. - Es. 4: lista con
appendin un ciclo di 10; massimo e minimo provvisori inizializzati conL[0]; non chiamarlimaxemin(nasconderebbero le funzioni predefinite);min(L),max(L); dà e (Liste in Pythonlist come sequenza mutabile (array dinamico); indici, slicing e assegnamento a fette; metodi e loro costo; aliasing, copia superficiale e profonda; list comprehension; liste annidate e matrici.Liste in Python →). - Es. 5:
np.random.randint(0, 50, size=100)ha l'estremo superiore escluso (valori 0..49; per includere 50 serve 51);m = v.mean();np.nonzero(v > m)[0]dà gli indici; conseed(0): media 22,5 e 48 elementi sopra la media. - Es. 6: prodotto che parte da 1; lista vuota gestita prima e restituisce 0;
[1,2,3,4]dà 24,[5]dà 5. - Es. 7:
tmp = s[::-1],tmp[:-1].lower() + tmp[-1].upper();"abcd""dcbA"; stringa vuota restituita subito. - Es. 8:
D[c] = D.get(c, 0) + 1;"ababcc"{'a': 2, 'b': 2, 'c': 2}; equivale acollections.Counter(Dizionari e insiemi in PythonADT mappa e insieme; dict con chiavi hashable, accesso, get, iterazione, conteggi e raggruppamenti; set e operazioni insiemistiche; tabelle hash e costo O(1) medio; Counter e defaultdict.Dizionari e insiemi in Python →, 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 →, 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 →). - Errori tipici: sommare stringhe invece di numeri (
'4' + '4'dà'44');>=al posto di>; dimenticare la stringa o lista vuota; credere cherandintincluda l'estremo superiore.