Salta al contenuto
Note per Studenti Esercizio - Python di base - input, liste, dizionari e funzioni (laboratorio 1)

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 2b+2h2b + 2h, area b⋅hb \cdot h.

python
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 2⋅5+2⋅3,5=17,02 \cdot 5 + 2 \cdot 3{,}5 = 17{,}0, area 17,517{,}5.

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.

python
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).

python
x = float(input('Insert value x: '))
y = float(input('Insert value y: '))

if x + y > 100:
    print('Number too large')

Prove: 60+50=110>10060 + 50 = 110 > 100 stampa il messaggio; 60+40=10060 + 40 = 100 non lo stampa (100 non "supera" 100); 100+0,5100 + 0{,}5 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].

python
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 [7,−2,15,3,3,0,9,15,−8,4][7, -2, 15, 3, 3, 0, 9, 15, -8, 4] il minimo è −8-8 e il massimo è 1515.

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 0,…,490, \dots, 49; 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.

python
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 22,522{,}5 e 48 elementi sopra la media, i primi nelle posizioni 0,1,5,9,100, 1, 5, 9, 10 con valori 44,47,39,36,2344, 47, 39, 36, 23 (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.

python
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]))            # 5

Esercizio 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 −1-1). 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.

python
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"))          # A

Per "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.

python
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

Teoria collegata