<jupyter_start><jupyter_text>Tuple [Scarica zip esercizi](../_static/generated/tuples.zip)[Naviga file online](https://github.com/DavidLeoni/softpython-it/tree/master/tuples)Una tupla in Python è una sequenza _immutabile_ di elementi eterogenei che ammette duplicati, perciò possiamo mettere gli oggetti che vogliamo, anche di tipi diversi, e anche ripetuti.  Che fare- scompatta lo zip in una cartella, dovresti ottenere qualcosa del genere: ```tuples    tuples1.ipynb    tuples1-sol.ipynb    tuples2-chal.ipynb        jupman.py         ```**ATTENZIONE**: Per essere visualizzato correttamente, il file del notebook DEVE essere nella cartella szippata.- apri il Jupyter Notebook da quella cartella. Due cose dovrebbero aprirsi, prima una console e poi un browser. Il browser dovrebbe mostrare una lista di file: naviga la lista e apri il notebook `tuples1.ipynb`- Prosegui leggendo il file degli esercizi, ogni tanto al suo interno troverai delle scritte **ESERCIZIO**, che ti chiederanno di scrivere dei comandi Python nelle celle successive.Scorciatoie da tastiera:* Per eseguire il codice Python dentro una cella di Jupyter, premi `Control+Invio`* Per eseguire il codice Python dentro una cella di Jupyter E selezionare la cella seguente, premi `Shift+Invio`* Per eseguire il codice Python dentro una cella di Jupyter E creare una nuova cella subito dopo, premi `Alt+Invio`* Se per caso il Notebook sembra inchiodato, prova a selezionare `Kernel -> Restart`  Creare tupleLe tuple si creano con le parentesi tonde `()` e separando gli elementi da virgole `,`.Qualche esempio:<jupyter_code>numeri = (6,7,5,7,7,9)
print(numeri)<jupyter_output>(6, 7, 5, 7, 7, 9)<jupyter_text>**Tuple di un solo elemento**: Puoi creare una tupla di un solo elemento **aggiungendo una virgola dopo l'elemento**:<jupyter_code>tuplina = (4,)  # occhio alla virgola !!!<jupyter_output><empty_output><jupyter_text>Verifichiamo che il tipo sia quello atteso:<jupyter_code>type(tuplina)<jupyter_output><empty_output><jupyter_text>Per vedere la differenza, scriviamo qua sotto `(4)` senza virgola e verifichiamo il tipo dell'oggetto ottenuto<jupyter_code>farlocca = (4)
type(farlocca)<jupyter_output><empty_output><jupyter_text>Vediamo che `farlocca` è un `int`, perchè il `4` è stato valutato come un'espressione dentro delle tonde e il risultato è il contenuto delle tonde  Tupla vuotaPossiamo anche creare una tupla vuota:<jupyter_code>vuota = ()
print(vuota)
type(vuota)<jupyter_output><empty_output><jupyter_text>Tuple senza parentesiQuando assegnamo dei valori a delle variabili, (e _solo_ quando assegnamo valori a delle variabili) è possibile usare una notazione del genere, in cui a sinistra dell' `=` mettiamo nomi di variabili e a destra una sequenza di valori:<jupyter_code>a,b,c = 1, 2, 3
a
b
c<jupyter_output><empty_output><jupyter_text>Se ci chiediamo cosa sia quel `1,2,3`, possiamo provare a mettere a sinistra solo una variabile:<jupyter_code># ATTENZIONE: MEGLIO EVITARE !
x = 1,2,3
type(x)<jupyter_output><empty_output><jupyter_text>Vediamo che Python ha considerato quel `1,2,3` come una tupla. Tipicamente, non scriverai mai assegnazioni con meno variabili che valori da metterci, ma se per caso ti capita, probabilmente ti troverai con qualche tupla indesiderata! **DOMANDA**: Guarda i seguenti frammenti di codice, e per ciascuno cerca di indovinare quale risultato produce (o se danno errore):1.  ```python    z,w = 5,6    print(type(z))    print(type(w))    ```1.  ```python    a,b = 5,6    a,b = b,a    print('a=',a)    print('b=',b)    ```1.  ```python    z = 5,    print(type(z))    ```1.  ```python    z = ,    print(type(z))    ```  Elementi eterogeneiIn una tupla possiamo mettere elementi di tipo diverso, come numeri e stringhe:<jupyter_code>roba = (4, "carta", 5, 2,"scatole", 7)
roba
type(roba)<jupyter_output><empty_output><jupyter_text>Possiamo anche inserire anche altre tuple:<jupyter_code>insalata = ( ("cavoli", 3), ("pomodori",9), ("verze",4) )
insalata
type(insalata)<jupyter_output><empty_output><jupyter_text>E anche liste:<jupyter_code>misto = ( ["quando", "fuori", "piove"], ["scrivo", "programmi"], [7,3,9] )<jupyter_output><empty_output><jupyter_text>**ATTENZIONE agli oggetti mutabili dentro le tuple!**Inserire oggetti _mutabili_ come le liste dentro le tuple potrebbe causare problemi in alcune situazioni - per es. se poi vuoi usare la tupla come elemento di un insieme o chiave di un dizionario (lo vedremo meglio nei rispettivi tutorial) Vediamo come gli esempi precedenti vengono rappresentati in Python Tutor:<jupyter_code># AFFINCHE' PYTHON TUTOR FUNZIONI, RICORDATI DI ESEGUIRE QUESTA CELLA con Shift+Invio
#   (basta eseguirla una volta sola, la trovi anche all'inizio di ogni foglio)

import sys
sys.path.append('../')
import jupman
roba = (4, "carta", 5, 2,"scatole", 7)
insalata = ( ("cavoli", 3), ("pomodori",9), ("verze",4) )
misto = ( ["quando", "fuori", "piove"], ["scrivo", "programmi"], [7,3,9] )

jupman.pytut()<jupyter_output><empty_output><jupyter_text>Creare tuple da sequenzePuoi creare una tupla da una qualsiasi sequenza, per esempio da una lista:<jupyter_code>tuple( [8,2,5] )<jupyter_output><empty_output><jupyter_text>Oppure una stringa (che è una sequenza di caratteri):<jupyter_code>tuple("abc")<jupyter_output><empty_output><jupyter_text>Creare sequenze da tuple Visto che la tupla è una sequenza, è anche possibile generare liste a partire da tuple:<jupyter_code>list( (3,4,2,3)  )<jupyter_output><empty_output><jupyter_text>**DOMANDA**: Ha senso creare una tupla da un'altra tupla così? Possiamo riscrivere il codice in modo più conciso?<jupyter_code>x = (4,2,5)
y = tuple(x)<jupyter_output><empty_output><jupyter_text>**RISPOSTA**: visto che una tupla è IMMUTABILE, una volta che abbiamo creato in memoria l'oggetto `(4,2,5)` siamo sicuri che nessuno lo modificherà, quindi non occorre creare una nuova tupla e possiamo scrivere direttamente```pythonx = (4,2,5)y = x``` **DOMANDA**: Guarda le seguenti espressioni, e per ciascuna cerca di indovinare quale risultato producono (o se danno errore):1.  ```python    (1.2,3.4)    ```1.  ```python        (1;2;3;4)    ```1.  ```python        (1,2;3,4)    ```1.  ```python        (1,2,3,4)    ```1.  ```python        (())    ```1.  ```python        type(())    ```1.  ```python        ((),)    ```1.  ```python        tuple([('a'),('b'),('c')])    ```1.  ```python        tuple(tuple(('z','u','m')))    ```1.  ```python        str(('a','b','c'))    ```1.  ```python        "".join(('a','b','c'))    ```  OperatoriI seguenti operatori funzionano sulle tuple e si comportano esattamente come per le liste:|Operatore|Risultato|Significato||---|---|----||`len`(tuple)|`int`|Ritorna la lunghezza di una tupla||tuple`[`int`]`|obj|Legge un elemento all'indice specificato||tuple`[`int`:`int`]`|`tuple`| Estrae una sotto-tupla - ritorna una NUOVA tupla||tuple `+` tuple|`tuple`|Concatena due tuple - ritorna una NUOVA tupla||obj `in` tuple|`bool`|Controlla se un elemento è presente in una tupla||tuple `*` int|`tuple`| Replica la tupla - ritorna una NUOVA tupla||`==`,`!=`|`bool`| Controlla se due tuple sono uguali o differenti|  len La funzione `len` ritorna la lunghezza della tupla:<jupyter_code>len( (4,2,3) )
len( (7,) )
len( () )<jupyter_output><empty_output><jupyter_text>**DOMANDA**: Guarda le seguenti espressioni, e per ciascuna cerca di indovinare il risultato (o se produce un errore)    1.  ```python    len(3,2,4)    ```1.  ```python        len((3,2,4))    ```1.  ```python        len(('a',))    ```1.  ```python        len(('a,'))    ```1.  ```python        len(((),(),()))    ```1.  ```python        len(len((1,2,3,4)))    ```1.  ```python        len([('d','a','c','d'),(('ab')),[('a','b','c')]])    ```  Leggere un elemento Come per stringhe e liste possiamo leggere un elemento ad una certa posizione con le quadre:<jupyter_code>#        0  1  2  3
tupla = (10,11,12,13)
tupla[0]
tupla[1]
tupla[2]
tupla[3]<jupyter_output><empty_output><jupyter_text>Anche per le tuple possiamo usare indici negativi:<jupyter_code>tupla[-1]<jupyter_output><empty_output><jupyter_text>**DOMANDA**: Guarda le espressioni seguenti e per ciascuna cerca di indovinare il risultato o se produce un errore:     1.  ```python    (1,2,3)[0]    ```1.  ```python        (1,2,3)[3]    ```1.  ```python        (1,2,3)0    ```1.  ```python        ()[0]    ```1.  ```python        (())[0]    ```1.  ```python        type((())[0])    ```1.  ```python        ('a,')[0]    ```1.  ```python        ('a',)[0]    ```1.  ```python        (1,2,3)[-0]    ```1.  ```python        (1,2,3)[-1]    ```1.  ```python        (1,2,3)[-3]    ```  Esercizio: animaliData la stringa `animali = "gatto siamese,cane,canarino,porcellino,coniglio,criceto"` 1. convertila in una lista2. crea una tupla di tuple dove ogni tupla ha due informazioni: il nome dell'animale e la lunghezza del nome, per esempio (("cane",3), ( "criceto",7))3. stampa la tuplaDovresti ottenere```bashgatto siamese,cane,canarino,porcellino,coniglio,criceto(('<NAME>amese', 13), ('cane', 4), ('canarino', 8), ('porcellino', 10), ('coniglio', 8), ('criceto', 7))```* puoi assumere che `animali` contenga sempre esattamente 6 animali<jupyter_code>animali = "gatto siamese,cane,canarino,porcellino,coniglio,criceto"

# scrivi qui
lista = animali.split(',')

#print(animali)
print()

tuple_animali = ( (lista[0], len(lista[0])), 
                  (lista[1], len(lista[1])), 
                  (lista[2], len(lista[2])), 
                  (lista[3], len(lista[3])),
                  (lista[4], len(lista[4])),
                  (lista[5], len(lista[5])))

#print(tuple_animali)<jupyter_output><jupyter_text>SliceCome per stringhe e liste possiamo ricavare sottosequenze da una tupla usando le _slice_, cioè scrivendo alla destra della tupla delle quadre con dentro un indice di partenza INCLUSO, due punti `:` e un indice di fine ESCLUSO:<jupyter_code>tupla = (10,11,12,13,14,15,16,17,18,19)
tupla[2:6]  # da indice 2 INCLUSO a 6 ESCLUSO<jupyter_output><empty_output><jupyter_text>Si può specificare di raccogliere elementi saltandone tra uno e l'altro aggiungendo il numero di elementi da saltare come un terzo numero tra le quadre, per esempio:<jupyter_code>tupla = (10,11,12,13,14,15,16,17)
tupla[0:8:5]
tupla[0:8:2]
tupla[1:8:1]<jupyter_output><empty_output><jupyter_text>**ATTENZIONE: ricordati che le slice producono una NUOVA tupla !** **DOMANDA**: Guarda il codice seguente e per ciascuna espressione prova a indovinare il risultato o se produce un errore:    1.  ```python    (7,6,8,9,5)(1:3)    ```1.  ```python        (7,6,8,9,5)[1:3]    ```1.  ```python        (10,11,12,13,14,15,16)[3:100]    ```1.  ```python        (10,11,12,13,14,15,16)[-3:5]    ```1.  ```python        (1,0,1,0,1,0)[::2]    ```1.  ```python        (1,2,3)[::1]    ```1.  ```python        (1,0,1,0,1,0)[1::2]    ```1.  ```python        tuple("cartolina")[0::2]    ```1.  ```python        (4,5,6,3,4,7)[0:::2]    ```  ConcatenazioneE' possibile concatenare due tuple usando l'operatore `+`, che crea una NUOVA tupla<jupyter_code>t = (1,2,3) + (4,5,6,7,8)
t
type(t)<jupyter_output><empty_output><jupyter_text>Verifichiamo che le tuple originali non vengano modificate:<jupyter_code>x = (1,2,3)
y = (4,5,6,7,8)
t = x + y
t
x
y<jupyter_output><empty_output><jupyter_text>Guardiamo come vengono rappresentate in Python Tutor:<jupyter_code># AFFINCHE' PYTHON TUTOR FUNZIONI, RICORDATI DI ESEGUIRE QUESTA CELLA con Shift+Invio
#   (basta eseguirla una volta sola, la trovi anche all'inizio di ogni foglio)

import sys
sys.path.append('../')
import jupman
x = (1,2,3)
y = (4,5,6,7,8)
t = x + y
print(t)
print(x)
print(y)

jupman.pytut()<jupyter_output>(1, 2, 3, 4, 5, 6, 7, 8)
(1, 2, 3)
(4, 5, 6, 7, 8)<jupyter_text>**DOMANDA**: Guarda il codice seguente e per ciascuna espressione cerca di indovinare il risultato, o se produce un errore.1.  ```python    ()+()    ```1.  ```python        type(()+())    ```1.  ```python        len(()+())    ```1.  ```python        ()+[]    ```1.  ```python        []+()    ```1.  ```python        (2,3,4) + tuple([5,6,7])    ```    1.  ```python        "razzo"+('p','a','z','z','o')    ```  Appartenenza Come per tutte le sequenze, se vogliamo verificare se un elemento è contenuto in una tupla possiamo usare l'operatore `in` che ci ritorna un valore booleano:<jupyter_code>'a' in ('c','a','s','c','o')
'z' in ('c','a','s','c','o')<jupyter_output><empty_output><jupyter_text>not inPer verificare se qualcosa **non** appartiene ad una tupla, possiamo usare due forme:**not in - forma 1**:<jupyter_code>"carota" not in ("anguria","banana","mela")
"anguria" not in ("anguria","banana","mela")<jupyter_output><empty_output><jupyter_text>**not in - forma 2**<jupyter_code>not "carota" in ("anguria","banana","mela")
not "anguria" in ("anguria","banana","mela")<jupyter_output><empty_output><jupyter_text>**DOMANDA**: Guarda le seguenti espressioni, e per ciascuna cerca di indovinare quale risultato producono (o se danno errore):    1.  ```python        3 in (1.0, 2.0,3.0)    ```1.  ```python        3.0 in (1,2,3)    ```1.  ```python        3 not in (3)    ```1.  ```python        3 not in (3,)    ```1.  ```python        6 not in ()    ```1.  ```python    0 in (0)[0]    ```1.  ```python        [] in ()    ```1.  ```python        () in []    ```1.  ```python        not [] in ()    ```1.  ```python        () in ()    ```1.  ```python        () in (())    ```1.  ```python        () in ((),)    ```1.  ```python        'ciao' in ('c','i','a','o')    ```  MoltiplicazionePer replicare gli elementi di una tupla, è possibile usare l’operatore `*` che produce una NUOVA tupla:<jupyter_code>(7,8,5) * 3
(7,8,5) * 1
(7,8,5) * 0<jupyter_output><empty_output><jupyter_text>**DOMANDA**: Il seguente codice cosa stamperà?```pythonx = (5,6,7)y = x * 3print('x=',x)print('y=',y)``` **RISPOSTA**: Stamperà```x = (5, 6, 7)y = (5, 6, 7, 5, 6, 7, 5, 6, 7)```perchè la moltiplicazione genera una NUOVA tupla che viene associata a `y`. La tupla associata a  `x` rimane invariata. **DOMANDA**: Guarda il codice seguente e per ciascuna espressione cerca di indovinare il risultato, o se produce un errore.    1.  ```python    (5,6,7)*(3.0)    ```1.  ```python        (5,6,7)*(3,0)    ```1.  ```python        (5,6,7)*(3)    ```1.  ```python        (5,6,7)*3    ```1.  ```python        (4,2,3)*int(3.0)    ```1.  ```python        (1,2)*[3][0]    ```1.  ```python        (1,2)*(3,4)[-1]    ```1.  ```python        [(9,8)]*4    ```1.  ```python    (1+2,3+4)*5    ```    1.  ```python    (1+2,)*4    ```1.  ```python    (1+2)*4    ```        1.  ```python    (1,2,3)*0    ```1.  ```python    (7)*0    ```1.  ```python    (7,)*0    ```  Esercizio - welcomeData una tupla `x` contenente esattamente 3 interi, ed una tupla `y` contenente esattamente 3 tuple di caratteri, scrivi del codice per creare una tupla `z` contenente ogni tupla di `y` replicata dal numero corrispondente in `x`.Esempio - dati:```pythonx = (2,4,3)y = (('w','e','l','c'),('o',),('m','e'))```dopo il tuo codice dovrebbe stampare:```python>>> print(z)('w', 'e', 'l', 'c', 'w', 'e', 'l', 'c', 'o', 'o', 'o', 'o', 'm', 'e', 'm', 'e', 'm', 'e')```<jupyter_code>#jupman-purge-output
x = (2,4,3)
y = (('w','e','l','c'),('o',),('m','e'))

# scrivi qui
z = y[0]*x[0] + y[1]*x[1] + y[2]*x[2] 

print(z)<jupyter_output>('w', 'e', 'l', 'c', 'w', 'e', 'l', 'c', 'o', 'o', 'o', 'o', 'm', 'e', 'm', 'e', 'm', 'e')<jupyter_text>Scrivere un elemento Le tuple sono _immutabili,_ quindi provare per esempio a scrivere un assegnazione  per mettere il numero `12` nella cella all'indice `3`  provoca un errore: ```python        0 1 2 3 4tupla = (5,8,7,9,11)tupla[3] = 666---------------------------------------------------------------------------TypeError                                 Traceback (most recent call last) in       1 tupla = (5,8,7,9)----> 2 tupla[1] = 666TypeError: 'tuple' object does not support item assignment``` Quello che possiamo fare è creare una NUOVA tupla componendola da sequenze prese dall'originale<jupyter_code>#        0  1  2  3  4  5  6
tupla = (17,54,34,87,26,95,34)
tupla =  tupla[0:3] + (12,) + tupla[4:]
tupla<jupyter_output><empty_output><jupyter_text>**ATTENZIONE:** `append`, `extend`, `insert`, `sort` **NON FUNZIONANO CON LE TUPLE !**Tutti i metodi che hai usato per modificare le liste _non_ funzioneranno con le tuple.    Esercizio - errandoProva a scrivere qua sotto `(1,2,3).append(4)` e guarda che errore appare:<jupyter_code># scrivi qui
#(1,2,3).append(4)<jupyter_output><empty_output><jupyter_text>Esercizio: abdeData una tupla `x`, salva nella variabile `y` un'altra tupla contenente:* all'inizio gli stessi elementi di `x` _eccetto_ l'ultimo* alla fine gli elementi `'d'` e `'e'` . * Il tuo codice dovrebbe funzionare con _qualunque_ tupla `x`Esempio```pythonx = ('a','b','c')```dopo il tuo codice, dovresti veder stampato:```bashx = ('a', 'b', 'c')y = ('a', 'b', 'd', 'e')```<jupyter_code>x = ('a','b','c')

# scrivi qui
y = x[:-1] + ('d','e')

#print('x=',x)
#print('y=',y)<jupyter_output><empty_output><jupyter_text>Esercizio - carismaticoData una tupla `t` avente caratteri intervallati maiuscolo / minuscolo, scrivere del codice che modifica l'assegnazione di `t` in modo che `t` sia uguale ad una tupla avente tutti i caratteri maiuscoli per primi e tutti i caratteri minuscoli per ultimi.Esempio - data```pythont = ('C', 'a', 'R', 'i', 'S', 'm', 'A', 't', 'I', 'c', 'O')```dopo il tuo codice deve risultare```python>>> print(t)('C', 'R', 'S', 'A', 'I', 'O', 'a', 'i', 'm', 't', 'c')```<jupyter_code>t = ('C', 'a', 'R', 'i', 'S', 'm', 'A', 't', 'I', 'c', 'O')

# scrivi qui
t = t[::2] + t[1::2]
#print(t)<jupyter_output><empty_output><jupyter_text>Esercizio - ordinareData una tupla `x` di numeri disordinati, scrivere del codice che cambia l'assegnazione di `x` in modo che abbia assegnata una tupla con i numeri ordinati.* il tuo codice deve funzionare per _qualsiasi_ tupla `x`* **SUGGERIMENTO**: Come già scritto, le tuple NON hanno il metodo `sort` (perchè le muterebbe), ma le liste ce l'hanno....Esempio - dati:```pythonx = (3,4,2,5,5,5,2,3)```dopo il tuo codice deve risultare ```python>>> print(x)(2, 2, 3, 3, 4, 5, 5, 5)```<jupyter_code>x = (3,4,2,5,5,5,2,3)

# scrivi qui
y = list(x)
y.sort()
x = tuple(y)
#print(x)<jupyter_output><empty_output><jupyter_text>MetodiLe tuple sono oggetti di tipo `tuple` e possiedono dei metodi che permettono di operare su di esse:|Metodo|Ritorna|Descrizione||-------|------|-----------||`tuple.index(obj)`|`int`|Trova la prima occorrenza di un elemento e ne ritorna la posizione||`tuple.count(obj)`|`int`|Conta le occorrenze di un elemento|  Metodo index Il metodo `index` ci permette di trovare l’indice della PRIMA occorrenza di un elemento.<jupyter_code>tupla = ('b','a','r','a','t','t','a','r','e')
tupla.index('b')
tupla.index('a')
tupla.index('t')<jupyter_output><empty_output><jupyter_text>Se l’elemento che cerchiamo non è presente, otterremo un errore: ```python>>> tupla.index('z')---------------------------------------------------------------------------ValueError                                Traceback (most recent call last) in ----> 1 tupla.index('z')ValueError: tuple.index(x): x not in tuple``` Opzionalmente, puoi specificare un indice da dove iniziare a cercare (**incluso**):<jupyter_code># 0   1   2   3   4   5   6   7   8
('b','a','r','a','t','t','a','r','e').index('r',3)<jupyter_output><empty_output><jupyter_text>E anche dove finire (**escluso**): ```python 0   1   2   3   4   5   6   7   8('b','a','r','a','t','t','a','r','e').index('r',3,7)---------------------------------------------------------------------------ValueError                                Traceback (most recent call last) in       1  0   1   2   3   4   5   6   7   8----> 2 ('b','a','r','a','t','t','a','r','e').index('r',3,7)ValueError: tuple.index(x): x not in tuple```  Non abusare index     **ATTENZIONE**: `index` **viene spesso usato in modo errato / inefficiente**Chiediti sempre:    1. la tupla su cui operare potrebbe contenere duplicati? Ricordati che solo il _primo_ verrà trovato!2. la tupla potrebbe _non_ contenere l'elemento cercato? Ricordati che in questo caso il programma lancerà un errore!    3. `index` compie una ricerca in tutta la tupla, che può essere inefficiente: è proprio necessaria, o sappiamo già l'intervallo in cui cercare? 4. se vogliamo sapere se un `elemento` è in una posizione nota a priori (es `3`), `index` non ci serve, basta scrivere `tupla[3] == elemento`. Usando `index` potrebbe trovare caratteri duplicati che stanno _prima_ o _dopo_ di quello che vogliamo verificare! **DOMANDA**: Guarda il codice seguente e per ciascuna espressione prova a indovinare il risultato o se produce un errore:    1.  ```python    (3,4,2).index(4)    ```1.  ```python        (3,4,---1).index(-1)    ```1.  ```python        (2.2,.2,2,).index(2)    ```1.  ```python        (3,4,2).index(len([3,8,2,9]))    ```1.  ```python        (6,6,6).index(666)    ```1.  ```python        (4,2,3).index(3).index(3)    ```1.  ```python        tuple("GUG").index("g")    ```1.  ```python        (tuple("ci") + ("a","o")).index('a')    ```    1.  ```python        (()).index(())    ```1.  ```python        ((),).index(())    ```  Esercizio - Le scatole cinesiScrivi del codice che cerca la parola `"Cinesi"` in ciascuna di 3 tuple una dentro l'altra, indicando la posizione relativa alla tupla che contiene l'occorrenza.- le tuple iniziano sempre con 4 stringheEsempio - data:```pythontupla = ('Apri','Le','Scatole','Cinesi', ('Scatole','Cinesi','Le','Apri', ('Apri','Le','Cinesi','Scatole')))```dopo il tuo codice, deve stampare:```('Apri', 'Le', 'Scatole', 'Cinesi') contiene Cinesi alla posizione 3('Scatole', 'Cinesi', 'Le', 'Apri') contiene Cinesi alla posizione 1('Apri', 'Le', 'Cinesi', 'Scatole') contiene Cinesi alla posizione 2```<jupyter_code>#jupman-purge-output
parola = 'Cinesi'
tupla = ('Apri','Le','Scatole','Cinesi', ('Scatole','Cinesi','Le','Apri', ('Apri','Le','Cinesi','Scatole')))
#                                 3                     1                                 2

#parola = 'c'
#tupla = ('a','b','c','d',('e','c','g','h',('a','b','d','c')))
#                  2            1                        3

# scrivi qui

t1 = tupla[:4]
t2 = tupla[4][:4]
t3 = tupla[4][4] 
i1 = t1.index(parola)
i2 = t2.index(parola)
i3 = t3.index(parola)

print(t1,"contiene", parola, "alla posizione", i1)
print(t2,"contiene", parola, "alla posizione", i2)
print(t3,"contiene", parola, "alla posizione", i3)<jupyter_output>('Apri', 'Le', 'Scatole', 'Cinesi') contiene Cinesi alla posizione 3
('Scatole', 'Cinesi', 'Le', 'Apri') contiene Cinesi alla posizione 1
('Apri', 'Le', 'Cinesi', 'Scatole') contiene Cinesi alla posizione 2<jupyter_text>Metodo countSi può ottenere il numero di occorrenze di un certo elemento in una lista usando il metodo `count`:<jupyter_code>t = ('g', 'u', 'a', 'r', 'a', 'n', 't', 'i', 'g', 'i', 'a')
t.count('g')
t.count('a')<jupyter_output><empty_output><jupyter_text>Se un elemento non è presente viene ritornato `0`:<jupyter_code>t.count('z')<jupyter_output><empty_output><jupyter_text>Non abusare count    **ATTENZIONE**: `count` **viene spesso usato in modo errato / inefficiente**Chiediti sempre:    1. la tupla potrebbe contenere duplicati? Ricordati che verranno tutti conteggiati!2. la tupla potrebbe _non_ contenere l'oggetto da contare? Ricordati di gestire anche questo caso!3. `count` compie una ricerca in tutta la tupla, che può essere inefficiente: è proprio necessaria, o sappiamo già l'intervallo in cui cercare? **DOMANDA**: Guarda i frammenti di codice seguenti, e per ciascuno cerca di indovinare che risultato produce (o se risulta in un errore).1.  ```python    ('p', 'o', 'r', 't', 'e', 'n', 't', 'o', 's', 'o').count('o')    ```1.  ```python    ('p', 'o', 'r', 't', 'e', 'n', 't', 'o', 's', 'o').count( ('o') )    ```1.  ```python    ('p', 'o', 'r', 't', 'e', 'n', 't', 'o', 's', 'o').count( ('o',) )    ```    1.  ```python    (1,0,0,0).count( 0 )    ```            1.  ```python    (1,0,0,0).count( (0) )    ```        1.  ```python    (1,0,0,0).count( (0,) )    ```    1.  ```python    (1,0,(0,),(0,)).count( (0,) )    ```        1.  ```python    (1,0,(0.0),((0,0),(0,0))).count( (0,0) )    ```          Esercizio: fruttiData la stringa `s = "mela|pera|mela|ciliegia|pera|mela|pera|pera|ciliegia|pera|fragola"`Inserisci gli elementi separati da `"|"` in una lista.    1. Quanti elementi deve avere la lista?2. Sapendo che la lista creata al punto precedente ha solo quattro elementi distinti (es `"mela"`, `"pera"`, `"ciliegia"`, e `"fragola"`), crea un'altra lista dove ogni elemento è una tupla contenente il nome del frutto e la sua moltiplicità (cioè il numero di volte che compare nella lista originale). Esempio:```pythonconteggi = [("mela", 3), ("pera",5), ...]```Qua puoi scrivere codice che funziona data una specifica costante, quindi non hai bisogno di cicli.3. Stampa il contenuto di ciascuna tupla in una linea separata (es: prima linea: `"mela"` è presente 3 volte)Dovresti ottenere:```bash['mela', 'pera', 'mela', 'ciliegia', 'pera', 'mela', 'pera', 'pera', 'ciliegia', 'pera', 'fragola'][('mela', 3), ('pera', 5), ('ciliegia', 2), ('fragola', 1)] mela  è presente  3  voltepera  è presente  5  volteciliegia  è presente  2  voltefragola  è presente  1  volte```<jupyter_code>s = "mela|pera|mela|ciliegia|pera|mela|pera|pera|ciliegia|pera|fragola"

# scrivi qui

parole = s.split("|")
#print(parole)

tmele = ("mela", parole.count("mela"))
tpere = ("pera", parole.count("pera"))
tciliegie = ("ciliegia", parole.count("ciliegia"))
tfragole = ("fragola", parole.count("fragola"))
conteggi =[tmele, tpere, tciliegie, tfragole]

#print(conteggi) 
#print()
#print(tmele[0], " è presente ", tmele[1], " volte")
#print(tpere[0], " è presente ", tpere[1], " volte")
#print(tciliegie[0], " è presente ", tciliegie[1], " volte")
#print(tfragole[0], " è presente ", tfragole[1], " volte")<jupyter_output><empty_output><jupyter_text>Esercizi con le funzioni**ATTENZIONE: Gli esercizi seguenti richiedono di conoscere:**   [Controllo di flusso](https://it.softpython.org/control-flow/control-flow-sol.html)   [Funzioni](https://it.softpython.org/functions/functions-sol.html)Se sei alle prime armi con la programmazione, ti conviene saltarli e ripassare in seguito  appaia✪✪ Scrivere una funzione `appaia` che data una tupla `t`, RITORNA una lista avente come elementi delle tuple da due elementi presi a due a due da `t`. * se la tupla `t` ha un numero dispari di elementi, l'ultima tupla nella lista da ritornare sarà costituita da un solo elementoEsempio : ```python>>> appaia( ('c', 'a', 'p', 'i', 'r', 'e') )    lunghezza pari[('c', 'a'), ('p', 'i'), ('r', 'e')]>>> appaia( ('t','a','p','p','e','t','o') )     lunghezza dispari[('t', 'a'), ('p', 'p'), ('e', 't'), ('o',)]```<jupyter_code># scrivi qui
def appaia(t):
    ret = []
    i = 0
    while i < len(t)-1:
        ret.append((t[i],t[i+1]))
        i += 2
    if i == len(t)-1:
        ret.append((t[-1],))
    return ret<jupyter_output><empty_output><jupyter_text>giunto✪✪ Scrivi una funzione che date due tuple di caratteri `ta` e `tb` aventi ciascuna caratteri diversi (possono essere anche vuote), se la tupla `ta` termina con lo stesso carattere con cui `tb` inizia, RITORNA la concatenazione di `ta` e `tb` SENZA caratteri duplicati, altrimenti RITORNA una tupla vuota.Esempio:```python>>> giunto(('a','b','c'), ('c','d','e'))('a', 'b', 'c', 'd', 'e')>>> giunto(('a','b'), ('b','c','d'))('a', 'b', 'c', 'd')>>> giunto((),('e','f','g'))()>>> giunto(('a',),('e','f','g'))()>>>  f(('a','b','c'),())()>>> f(('a','b','c'),('d','e'))()```<jupyter_code># scrivi qui

def giunto(ta,tb):
    if len(ta) > 0 and len(tb) > 0:
        if ta[-1] == tb[0]:
            return ta[:-1] + tb

    return ()<jupyter_output><empty_output><jupyter_text>Verifica comprensione**ATTENZIONE**Gli esercizi che segueno contengono dei test con gli _assert_. Per capire come svolgerli, leggi prima [Gestione errori e testing](https://it.softpython.org/errors-and-testing/errors-and-testing-sol.html)   doppie✪✪ Prende in input una lista con `n` numeri interi, e RITORNA una NUOVA lista che contiene `n` tuple ciascuna da due elementi. Ogni tupla contiene un numero preso dalla corrispondente posizione della lista di partenza, e il suo doppio. Per esempio:```pythondoppie([ 5, 3, 8])```deve dare la nuova lista```python[(5,10), (3,6), (8,16)]```<jupyter_code>def doppie(lista):
    #jupman-raise
    ret = []
    for elemento in lista:
        ret.append((elemento, elemento * 2))
    return ret
    #/jupman-raise

# INIZIO TEST - NON TOCCARE !
assert doppie([]) == []
assert doppie([3]) == [(3,6)]
assert doppie([2,7]) == [(2,4),(7,14)]
assert doppie([5,3,8]) == [(5,10), (3,6), (8,16)]

# verifica che la lista originale non venga cambiata 
la = [6]
lb = doppie(la)
assert la == [6]
assert lb == [(6,12)]
# FINE TEST<jupyter_output><empty_output><jupyter_text>nasty✪✪✪ Date due tuple `ta` di caratteri e `tb` di numeri interi positivi, scrivere una funzione `nasty` che RITORNA una tupla avente stringhe da due caratteri: il primo carattere è preso da `ta`, e il secondo carattere è un numero preso dalla posizione corrispondente in `tb`.Le stringhe vengono ripetute per un numero di volte pari a quel numero.```python>>> nasty(('u','r','g'), (4,2,3))('u4', 'u4', 'u4', 'u4', 'r2', 'r2', 'g3', 'g3', 'g3')>>> nasty(('g','a','s','p'), (2,4,1,3))('g2', 'g2', 'a4', 'a4', 'a4', 'a4', 's1', 'p3', 'p3', 'p3')```<jupyter_code>def nasty(ta, tb):
    #jupman-raise
    i = 0
    ret = []
    while i < len(tb):
        s = ta[i]+str(tb[i])    
        ret.extend( (s,) * tb[i] )
        i += 1
    return tuple(ret)
    #/jupman-raise
        
# INIZIO TEST - NON TOCCARE !        
assert nasty(('a',), (3,)) == ('a3','a3','a3')
assert nasty(('a','b'), (3,1)) == ('a3','a3','a3','b1')
assert nasty(('u','r','g'), (4,2,3)) == ('u4', 'u4', 'u4', 'u4', 'r2', 'r2', 'g3', 'g3', 'g3')
assert nasty(('g','a','s','p'), (2,4,1,3)) == ('g2', 'g2', 'a4', 'a4', 'a4', 'a4', 's1', 'p3', 'p3', 'p3')
# FINE TEST<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1942950122866441, 'fraction_numerical': 0.030683403068340307, 'mean_word_length': 4.191346319600069, 'pattern_counts': {'":': 0, '<': 175, '<?xml version=': 0, '>': 221, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 17, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '44', 'dir': 'jupyter-structured-clean-dedup', 'id': '368596', 'license': 'CC-BY-4.0', 'n_tokens_mistral': 12266, 'n_tokens_neox': 12055, 'n_words': 3209, 'path': 'tuples/tuples1-sol.ipynb', 'repo_name': 'DavidLeoni/softpython-', 'size': '30116'}