<jupyter_start><jupyter_text>Esercitazione 1: Hello Worldv1![](https://imgs.xkcd.com/comics/python.png)(Nota: in python 3, Hello World e' `print("Hello, world!")`, con le parentesi.)  IstruzioniScrivi il programma Python nella cella sotto il testo dell'esercizio (o creane una nuova usando il tasto "+" in alto a sx). Stampa sempre a video il risultato finale per verificare la correttezza dell'esercizio.  Talvolta richiamiamo alcuni concetti importanti in una cella di codice sotto il testo dell'esercizio, prova a eseguirla ed eventualmente modificarla per assicurarti di aver capito il necessario.Suggerimento: per eseguire una cella di codice, digita `CTRL+Enter` mentre la cella e' selezionata.Ricorda: tutte le variabili assegnate in precedenza rimangono in memoria! Se vuoi, puoi azzerare lo stato della memoria eseguendo dal menu' sopra: `Kernel -> Restart & Clear Outputs`. ConsegnaPer tutte le esercitazioni, e' obbligatorio **consegnare la soluzione di tutti gli esercizi** (tranne quelli marcati come opzionali) **entro l'inizio della lezione successiva**, nell'apposito assignment su iCorsi.  Per consegnare:- eseguire l'intero notebook partendo da zero (`Kernel -> Restart & Run All`), e controllare che le soluzioni siano quelle attese;- esportare il notebook in formato html (`File -> Download as...`) e consegnare il file risultante.Nel caso non abbiate potuto completare uno o piu' esercizi, descrivete il problema incontrato e **consegnate comunque il file con il resto delle soluzioni**. SoluzioniDurante la lezione successiva verranno pubblicate (ed eventualmente discusse) le soluzioni agli esercizi.  Controllatele sempre e confrontatele con le vostre.  Se qualcosa non e' chiaro, contattate i docenti per email. Dove cercare aiutoQuasi tutto quello che ci serve sta scritto da qualche parte qua dentro: [Python tutorial](https://docs.python.org/3.6/tutorial/index.html).  Di particolare interesse per ora: [Basics](https://docs.python.org/3.6/tutorial/introduction.html), [Controllo di flusso](https://docs.python.org/3.6/tutorial/controlflow.html) (if, for, while...), [Strutture dati](https://docs.python.org/3.6/tutorial/datastructures.html) (liste, set, dict).  [Qui](https://docs.python.org/3.6/tutorial/inputoutput.htmlfancier-output-formatting) trovate molte info sulla formattazione di stringhe.  Se mai ci fosse bisogno, [qui](https://docs.python.org/3.6/library/index.html) c'e' la documentazione completa della standard library.  Per cercare una keyword nella documentazione usate la quick search box in alto a destra.![image.png](attachment:image.png)Oppure usate google.  Attenzione in questo caso che stiamo usando Python 3.  Fino a qualche anno fa, era ancora maggioritario Python 2, quindi potreste trovare alcuni suggerimenti per quella versione.  Ad esempio, in python 2 `print` non aveva bisogno di parentesi.  Esercizi facili di riscaldamentoPer prendere un po' di confidenza con il linguaggio 0.1Chiedi all'utente il nome, poi salutalo<jupyter_code># Hints
risposta = input("Domanda? ") # Ottenere input (stringa) dall'utente
print(f"La risposta e' {risposta}") # Formattare una stringa
# Soluzione
nome = input(f"come ti chiami? ")
print(f"Ciao, {nome}")<jupyter_output>come ti chiami? cia
Ciao, cia<jupyter_text>0.2Saluta l'utente N volte, dove N e' inserito dall'utente<jupyter_code># Hints
variabile_stringa = "5"
variabile_intera = int(variabile_stringa) # cast
print(type(variabile_stringa), type(variabile_intera))

# questo funziona...
for i in range(variabile_intera):
    print(i)
    
# questo no!
#for i,n in variabile_stringa:
#    print(i)
# soluzione
n = input("Quante volte ti saluto? ")
n = int(n)
for i in range(n):
    print("ciao")<jupyter_output>Quante volte ti saluto? 3
ciao
ciao
ciao<jupyter_text>0.3Stampa una matrice 5x5 tipo questa, usando due cicli for innestati.```1  2  3  4  52  4  6  8 103  6  9 12 154  8 12 16 205 10 15 20 25```<jupyter_code># Hints
print("1 ", end="") # Non stampa il newline in fondo
print("2") # Di default invece stampa il newline in fondo
print("1\t2\t3\t4") # \t e' un carattere di tabulazione, come in Java
a = 2
b = 3
print(f"a = {a}; b = {b}; a + b = {a+b}") # dentro le {} potete mettere qualsiasi espressione!
# Soluzione
for i in range(1,6):
    for j in range(1,6):
        print(f"{j*i}\t", end="")
    print()<jupyter_output>1	2	3	4	5	
2	4	6	8	10	
3	6	9	12	15	
4	8	12	16	20	
5	10	15	20	25<jupyter_text>0.4 FizzStampa i numeri da 1 a 20, uno per riga.  Ma se il numero e' divisibile per 3, invece del numero, stampa "Fizz".  Usa l'operatore `%` per ottenere il resto della divisione tra due interi, come in Java.  Se vuoi, impara le funzionalita' di `range` leggendo la sua [documentazione](https://docs.python.org/3.6/library/stdtypes.html?highlight=rangerange) (specialmente gli esempi).<jupyter_code># Soluzione
for i in range(1,21):
    val = "Fizz" if i%3==0 else i
    print(f"{val}")<jupyter_output>1
2
Fizz
4
5
Fizz
7
8
Fizz
10
11
Fizz
13
14
Fizz
16
17
Fizz
19
20<jupyter_text>0.5 Fizz Buzz![](https://cdn-images-1.medium.com/max/1600/1*lPfdDAivK_QNzqknqLCP8w.png)Stampa i numeri da 1 a 20, uno per riga. Ma:- se il numero e' divisibile per 3, invece del numero, stampa `Fizz!`;- se il numero e' divisibile per 5, invece del numero, stampa `Buzz!`;- se il numero e' divisibile sia per 3 che per 5, invece del numero, stampa `FizzBuzz!`.Sembra semplice, ma [non datelo troppo per scontato](https://blog.codinghorror.com/why-cant-programmers-program/).<jupyter_code># Hint
a = 5
if (a > 3) and (a < 7):
    print("Si")
else:
    print("No")    
# Soluzione
for i in range(1,21):
    val = i
    if(i%3==0 and i%5==0):
        val = "FizzBuzz!"
    elif(i%3==0):
        val = "Fizz!"
    elif(i%5==0):
        val = "Buzz!"
    print(f"{val}")<jupyter_output>1
2
Fizz!
4
Buzz!
Fizz!
7
8
Fizz!
Buzz!
11
Fizz!
13
14
FizzBuzz!
16
17
Fizz!
19
Buzz!<jupyter_text>Esercizio 1 (liste)La successione di Fibonacci è una sequenza di numeri interi in cui i primi due elementi sono 1, e i successivi elementi sono dati dalla somma dei due precedenti (es. `[1,1,2,3,5,8,13,21...]`) ![Fibonacci](https://images.wired.it/wp-content/uploads/2017/11/23130621/1511435180_Fibonacci-1050x590.jpg)([info](https://www.wired.it/play/cultura/2017/11/23/fibonacci-day-numeri/)) 1.1Scrivi un programma che generi una lista (che chiameremo `listFib`) contenete la successione di Fibonacci con tutti i numeri minori o uguali di $200$ (in altre parole, l'ultimo elemento della lista deve essere un numero minore o uguale di $200$).  Suggerimento: inizializza la lista con i primi due elementi `listFib = [1,1]` e poi estendila. _Da quanti elementi è composta la lista?_<jupyter_code>#Hint 
lista = [10,20,30]
print(len(lista)) # Lunghezza lista (un int)

lista.append(40)  # Aggiungere elemento ad una lista 
print(lista)

while(True):
    if len(lista) < 6:
        print("Aggiungo un elemento alla lista")
        lista.append("Nuovo elemento")
    else:
        print('Esco dal ciclo while')
        break # Esci dal ciclo while
        
print(lista) # Nota che la lista puo' contenere tipi qulsiasi

print(f"Il primo elemento della lista e' {lista[0]}")
print(f"Il terzultimo elemento della lista e' {lista[-3]}")
# Hint: come iterare su una lista:
for elem in lista:  # Non c'e' bisogno di definire un indice i!
    print(elem)
# Soluzione 
listFib=[1,1]
last = 1
i = 0
while(True):
    last = listFib[i]+listFib[i+1]
    if(last>=200):
        break
    i=i+1
    listFib.append(last)
    print(f"\t{last}")        
print(len(listFib))<jupyter_output>2
	3
	5
	8
	13
	21
	34
	55
	89
	144
12<jupyter_text>1.2Esegui `listFib * 2` ed esamina il risultato.  Hai capito cosa e' successo?E cosa succede se esegui `listFib * 1.5`?<jupyter_code>listFib<jupyter_output><empty_output><jupyter_text>1.3Crea una nuova lista `listFib2`. Ogni elemento della nuova lista è uguale all'elemento corrispondente della list `listFib` moltiplicato per due. Suggerimento: conviene inizializzare una lista vuota con il comando `lista = []` (oppure, equivalentemente, `lista = list()`) e poi riempirla durante l'esecuzione del codice con il comando `lista.append(elemento)`.<jupyter_code># Soluzione
lista = []
for i in listFib:
    lista.append(i*2)
lista<jupyter_output><empty_output><jupyter_text>1.4Si generi una nuova lista `listRatio` dove l'elemento in posizione $i$ è uguale a $\frac{listFib[i+1]}{listFib[i]}$.<jupyter_code># Soluzione
lista = []
for i in range(1,len(listFib)):
    lista.append(listFib[i]/listFib[i-1])
lista<jupyter_output><empty_output><jupyter_text>1.5Genera una lista `newList` che contenga tutti i numeri tra 5 e 100 (compresi) che _non_ appartengono alla serie di Fibonacci. Suggerimento: L'operatore `in` restituisce `True` se l'elemento a sinistra appartiene alla lista a destra; `not in` per controllare se non appartiene.<jupyter_code># Hint
print(1 in [1,2,3])
print(0 in [1,2,3])
print(0 not in [1,2,3])    
# Soluzione
print(listFib)
newList = []
for i in range(5, 101):
    if(i not in listFib):
        newList.append(i)
        
print(newList)<jupyter_output>[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]
[6, 7, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]<jupyter_text>1.6Scrivere un programma che generi una lista di liste (ogni elemento della lista è una lista). Nello specifico, la lista da generare dovrà essere composta da 2 liste: la prima contenete tutti i numeri pari tra quelli in `listFib`, la seconda tutti i numeri dispari.<jupyter_code># Soluzione
pari=[]
dispari=[]
for i in listFib:
    if i%2==0:
        pari.append(i)
    else:
        dispari.append(i)
        
listList = [pari,dispari]
print(listList)<jupyter_output>[[2, 8, 34, 144], [1, 1, 3, 5, 13, 21, 55, 89]]<jupyter_text>1.7 (opzionale)Simile al punto 3. Sia data la lista listFib generata al passo 1. Per tutti i numeri interi da $5$ a $10$ verificare se il numero è presente nella lista. Se non è presente, aggiungerlo rispettando l'ordine crescente degli elementi della lista. Se invece è presente, allora toglierlo dalla lista. Metodi utili: remove, insert. Vedere cella sotto per capire come funzionano<jupyter_code># Hint
lista = [10,20,30,40,60]
lista.insert(1,13) # Inserisco il numero 13 nella posizion con indice 1 
print(lista)

lista.remove(30) # Rimuovo il numero 30
print(lista)
# Soluzione
listFib = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]
print(listFib)

for i in range(5,11):
    if(i in listFib):
        listFib.remove(i)
    else:
        for idx,x in enumerate(listFib):
            if(x>i):
                listFib.insert(idx, i)
                break
print(listFib)<jupyter_output>[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]
[1, 1, 2, 3, 6, 7, 9, 10, 13, 21, 34, 55, 89, 144]<jupyter_text>Esercizio 2 (dizionari)I dizionari sono analoghi alle HashMap in Java, e funzionano nello stesso modo. [Qui](http://introtopython.org/dictionaries.html) trovate un'ottima introduzione molto graduale.  Si usano moltissimo e quindi e' importante saperli manipolare. Introduzione molto rapida.<jupyter_code>pop = dict() # Crea un dizionario vuoto
pop["Manno"] = 1318 # Aggiunta chiave-valore
pop["Bioggio"] = 2648
pop["Lugano"] = 63932
# Equivalente:
# pop = {"Manno" : 1318, "Bioggio" : 2648, "Lugano" : 63932}
print(pop)
print(pop["Manno"]) # Interrogazione
print(pop.keys()) # Tutte le chiavi: agisce come una lista
print("Lugano" in pop.keys())
print(pop.items()) # Restituisce una lista di tuple, ciascuna delle quali contiene due elementi: chiave e valore
# Per la precisione non e' una lista, ma e' un oggetto su cui si puo' iterare come se fosse una lista
for tupla in pop.items(): # ogni elemento della simil-lista di cui sopra
    k = tupla[0]
    v = tupla[1]
    print(f"Key={k}, Value={v}")
# Ancora meglio (usa una funzione comodissima nota come tuple unpacking)
for tupla in pop.items():
    k,v = tupla # assegna il primo e il secondo elemento di tupla a k e v rispettivamente
    print(f"Key={k}, Value={v}")
# Ancora meglio
for k,v in pop.items():
    print(f"Key={k}, Value={v}")<jupyter_output>Key=Manno, Value=1318
Key=Bioggio, Value=2648
Key=Lugano, Value=63932<jupyter_text>2.1Si costruisca un dizionario con almeno 5 elementi (generati a vostro piacimento) dove a un nome di una persona è associata la sua età (nello specifico, ogni elemento del dizionario dovrà avere come chiave (key) il nome di una persona, e come valore (value) l'età.<jupyter_code># Soluzione
d = dict()
d["a"] = "alfa"
d["b"] = "beta"
d["c"] = "gamma"
d["d"] = "delta"
d["e"] = "epsilon"

print(d)<jupyter_output>{'a': 'alfa', 'b': 'beta', 'c': 'gamma', 'd': 'delta', 'e': 'epsilon'}<jupyter_text>2.2Data una nuova lista di nomi, stampa la stringa `"{nome} ha {età} anni"` (es. "Luca ha 22 anni") per ogni nome presente nel dizionario. Se il nome non è nel dizionario, stampa `"{nome} non è presente nel dizionario"` (es. "Antonio non è presente nel dizionario"). Aiuto: per creare un iterable con le chiavi di un dizionario, usare il metodo `keys()` del dizionario (vedi cella sotto per esempio).<jupyter_code># Hint
dizionario = {"Albero": ("tronco", "rami"), "Fiore": ("stelo","petalo")};
for name in dizionario.keys():
    print(name)
# Soluzione
list = ["a", "b", "g"]
for e in list:
    if(e not in d.keys()):
        print(f"{e} non in dizionario ");
    else:
        print(f"{e} = {d[e]}")<jupyter_output>a = alfa
b = beta
g non in dizionario<jupyter_text>2.3Si scriva un programma che per ogni elemento del dizionario stampi la seguente stringa `{nome} ha {età} anni`.Aiuto: per accedere agli elementi del dizionario uno per uno (considerando le coppie `key,value` corrispondenti) usare il metodo `items()` come mostrato sopra e nell'esempio sotto.<jupyter_code># Hint

for name, age in dizionario.items():
    print(f"{name} {age}")
# Soluzione
a = (1, 2, 4)
a<jupyter_output><empty_output><jupyter_text>2.4Creare un nuovo dizionario che contenga tutti gli elementi del dizionario precedente con età compresa tra $23$ anni (inclusi) e $60$ anni (esclusi).<jupyter_code># Soluzione<jupyter_output><empty_output><jupyter_text>Esercizio 3 (stringhe)  3.1Si scriva un programma Python che chieda all'utente di inserire una frase con almeno 10 parole. Per semplicità la frase non dovrà contenere punteggiatura. Esempio di frase che l'utente potrà inserire: "Oggi è una bella giornata Domani sarà una bellissima giornata". Comando utile per inserire una stringa da linea di comando: inputUna volta inserita la frase, si scriva un programma che conti:- il numero di parole all'interno della frase. Comando utile per creare lista dividere la stringa in parole: `split` ([documentazione](https://docs.python.org/3.6/library/stdtypes.htmlstr.split))- il numero di occorrenze di ogni parola all'interno della frase. Nello specifico, si crei un dizionario dove la chiave è la parola, e il valore il numero di occorrenze della parola. Nel conteggio delle occorrenze non si faccia distinzione tra lettere maiuscole e minuscole.- il numero di occorrenze di ogni lettera all'interno della frase. Nello specifico, si crei un dizionario simile a quello sopra. Nel conteggio delle occorrenze non si faccia distinzione tra lettere maiuscole e minuscole.    La cella sotto mostra come funzionano i comandi `input` e `split`<jupyter_code># Hint
stringa = input("Inserire una frase: ")
parole = stringa.split()
print(parole)
# Soluzione
str = input("insert: ")
parole = str.split()
d = dict()
for p in parole:
    if p in d:
        d[p] = d[p] + 1
    else:
        d[p] = 1

d1 = dict()
for p in parole:
    for l in p:
        ll = l.lower()
        if ll in d1:
            d1[ll] = d1[ll] + 1
        else:
            d1[ll] = 1
        
        
print(d1)<jupyter_output>insert: il numero di occorrenze di ogni parola all'interno della frase. Nello specifico, si crei un dizionario dove la chiave è la parola, e il valore il numero di occorrenze della parola. Nel conteggio delle occorrenze non si faccia distinzione tra lettere maiuscole e minuscole
{'i': 24, 'l': 23, 'n': 18, 'u': 5, 'm': 4, 'e': 30, 'r': 18, 'o': 25, 'd': 9, 'c': 15, 'z': 5, 'g': 3, 'p': 4, 'a': 19, "'": 1, 't': 6, 'f': 3, 's': 7, '.': 2, ',': 2, 'v': 3, 'h': 1, 'è': 1}<jupyter_text>3.2 (opzionale)Si scriva un programma Python che, data una stringa (senza punteggiatura), generi una nuova stringa rimovendo eventuali parole duplicate. Nel conteggio delle parole duplicate, non si faccia distinzione tra lettere maiuscole e minuscole. Comandi utili per creare una stringa a partire da una lista: `join` [documentazione](https://docs.python.org/3.6/library/stdtypes.htmlstr.join)<jupyter_code># Hint
listaParole = ['ciao', 'a', 'tutti']
stringa = " ".join(listaParole)
print(stringa)
# Soluzione
frase = "il numero di occorrenze di ogni parola all'interno della frase. Nello specifico, si crei un dizionario dove la chiave è la parola, e il valore il numero di occorrenze della parola. Nel conteggio delle occorrenze non si faccia distinzione tra lettere maiuscole e minuscole"
frase = frase.lower()
parole = set(frase.split())
stringa = " ".join(parole)
print(stringa)<jupyter_output>ogni si valore specifico, e crei delle della conteggio occorrenze nel numero frase. chiave nello dove parola. è tra parola, non minuscole di il maiuscole dizionario all'interno la lettere distinzione faccia un parola
{'fraction_non_alphanumeric': 0.11570200899208924, 'fraction_numerical': 0.04262705594445393, 'mean_word_length': 4.426806670784435, 'pattern_counts': {'":': 3, '<': 65, '<?xml version=': 0, '>': 69, 'https://': 14, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 31, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '19', 'dir': 'jupyter-structured-clean-dedup', 'id': '223156', 'license': 'MIT', 'n_tokens_mistral': 7185, 'n_tokens_neox': 6816, 'n_words': 2259, 'path': 'notebook/Esercitazione 01 max.ipynb', 'repo_name': 'code-mds/datascience', 'size': '17571'}