Previous Up Next

Buy this book at Amazon.com

Chapter 10  Liste

Questo capitolo illustra uno dei più utili tipi predefiniti di Python, le liste. Imparerete anche altri dettagli sugli oggetti, e vedrete cosa succede in presenza di uno stesso oggetto con più nomi.

10.1  Una lista è una sequenza

Come una stringa, una lista è una sequenza di valori. Mentre in una stringa i valori sono dei caratteri, in una lista possono essere di qualsiasi tipo. I valori che fanno parte della lista sono chiamati elementi.

Ci sono parecchi modi di creare una nuova lista, e quello più semplice è racchiudere i suoi elementi tra parentesi quadrate ([ e ]):

[10, 20, 30, 40]
['Primi piatti', 'Secondi piatti', 'Dessert']

Il primo esempio è una lista di quattro interi, il secondo una lista di tre stringhe. Gli elementi di una stessa lista non devono necessariamente essere tutti dello stesso tipo. La lista che segue contiene una stringa, un numero in virgola mobile, un intero e (meraviglia!) un’altra lista:

['spam', 2.0, 5, [10, 20]]

Una lista all’interno di un’altra lista è detta lista nidificata.

Una lista che non contiene elementi è detta lista vuota; potete crearne una scrivendo le due parentesi quadre vuote, [].

Avrete già intuito che potete assegnare i valori della lista a variabili:

>>> formaggi = ['Cheddar', 'Edam', 'Gouda']
>>> numeri = [42, 123]
>>> vuota = []
>>> print(formaggi, numeri, vuota)
['Cheddar', 'Edam', 'Gouda'] [42, 123] []

10.2  Le liste sono mutabili

La sintassi per l’accesso agli elementi di una lista è la stessa che abbiamo già visto per i caratteri di una stringa: le parentesi quadre, con un’espressione tra parentesi che specifica l’indice dell’elemento (non dimenticate che gli indici partono da 0!):

>>> formaggi[0]
'Cheddar'

A differenza delle stringhe, le liste sono mutabili. Quando l’operatore parentesi quadre compare sul lato sinistro di un’assegnazione, identifica l’elemento della lista che sarà riassegnato:

>>> numeri = [42, 123]
>>> numeri[1] = 5
>>> numeri
[42, 5]

L’elemento di indice 1 di numeri, che era 123, ora è 5

La Figura 10.1 mostra il diagramma di formaggi, numeri e vuota:


Figure 10.1: Diagramma di stato

Le liste sono rappresentate da riquadri con la parola “list” all’esterno e i suoi elementi all’interno. formaggi si riferisce a una lista con tre elementi di indice 0, 1 e 2. numeri contiene due elementi; il diagramma mostra che il valore del secondo elemento è stato riassegnato da 123 a 5. vuota si riferisce a una lista senza elementi.

Gli indici di una lista funzionano nello stesso modo già visto per le stringhe:

  • Come indice possiamo usare qualsiasi espressione che produca un intero.
  • Se tentate di leggere o modificare un elemento che non esiste, ottenete un messaggio d’errore IndexError.
  • Se un indice ha valore negativo, il conteggio parte dalla fine della lista.

Anche l’operatore in funziona con le liste:

>>> formaggi = ['Cheddar', 'Edam', 'Gouda']
>>> 'Edam' in formaggi
True
>>> 'Brie' in formaggi
False

10.3  Attraversamento di una lista

Il modo più frequente di attraversare gli elementi di una lista è un ciclo for. La sintassi è la stessa delle stringhe:

for formaggio in formaggi:
    print(formaggio)

Questo metodo funziona bene per leggere gli elementi di una lista, ma se volete scrivere o aggiornare degli elementi vi servono gli indici. Un modo per farlo è usare una combinazione delle funzioni predefinite range e len:

for i in range(len(numeri)):
    numeri[i] = numeri[i] * 2

Questo ciclo attraversa la lista e aggiorna tutti gli elementi. len restituisce il numero di elementi della lista. range restituisce una lista di indici da 0 a n−1, dove n è la lunghezza della lista. Ad ogni ripetizione del ciclo, i prende l’indice dell’elemento successivo. L’istruzione di assegnazione nel corpo usa i per leggere il vecchio valore dell’elemento e assegnare quello nuovo.

Un ciclo for su una lista vuota non esegue mai il corpo:

for x in []:
    print('Questo non succede mai.')

Sebbene una lista possa contenerne un’altra, quella nidificata conta sempre come un singolo elemento. Quindi la lunghezza di questa lista è quattro:

['spam', 1, ['Brie', 'Roquefort', 'Pol le Veq'], [1, 2, 3]]

10.4  Operazioni sulle liste

L’operatore + concatena delle liste:

>>> a = [1, 2, 3]
>>> b = [4, 5, 6]
>>> c = a + b
>>> c
[1, 2, 3, 4, 5, 6]

L’operatore * ripete una lista per un dato numero di volte:

>>> [0] * 4
[0, 0, 0, 0]
>>> [1, 2, 3] * 3
[1, 2, 3, 1, 2, 3, 1, 2, 3]

Il primo esempio ripete [0] per quattro volte. Il secondo ripete la lista [1, 2, 3] per tre volte.

10.5  Slicing delle liste

Anche l’operazione di slicing funziona sulle liste:

>>> t = ['a', 'b', 'c', 'd', 'e', 'f']
>>> t[1:3]
['b', 'c']
>>> t[:4]
['a', 'b', 'c', 'd']
>>> t[3:]
['d', 'e', 'f']

Se omettete il primo indice, lo slicing comincia dall’inizio, mentre se manca il secondo, termina alla fine. Se vengono omessi entrambi, lo slicing è una copia dell’intera lista.

>>> t[:]
['a', 'b', 'c', 'd', 'e', 'f']

Dato che le liste sono mutabili, spesso è utile farne una copia prima di eseguire operazioni che le modificano.

Un operatore di slicing sul lato sinistro di un’assegnazione, permette di aggiornare più elementi.

>>> t = ['a', 'b', 'c', 'd', 'e', 'f']
>>> t[1:3] = ['x', 'y']
>>> t
['a', 'x', 'y', 'd', 'e', 'f']

10.6  Metodi delle liste

Python fornisce dei metodi che operano sulle liste. Ad esempio, append aggiunge un nuovo elemento in coda alla lista:

>>> t = ['a', 'b', 'c']
>>> t.append('d')
>>> t
['a', 'b', 'c', 'd']

extend prende una lista come argomento e accoda tutti i suoi elementi:

>>> t1 = ['a', 'b', 'c']
>>> t2 = ['d', 'e']
>>> t1.extend(t2)
>>> t1
['a', 'b', 'c', 'd', 'e']

Questo esempio lascia immutata la lista t2.

sort dispone gli elementi della lista in ordine crescente:

>>> t = ['d', 'c', 'e', 'b', 'a']
>>> t.sort()
>>> t
['a', 'b', 'c', 'd', 'e']

La maggior parte dei metodi delle liste sono vuoti: modificano la lista e restituiscono None. Se scrivete accidentalmente t = t.sort(), il risultato vi deluderà.

10.7  Mappare, filtrare e ridurre

Per sommare tutti i numeri in una lista, potete usare un ciclo come questo:

def somma_tutti(t):
    totale = 0
    for x in t:
        totale += x
    return totale

totale è inizializzato a 0. Ad ogni ripetizione del ciclo, x prende un elemento dalla lista. L’operatore += è una forma abbreviata per aggiornare una variabile. Questa istruzione di assegnazione potenziata,

    totale += x

è equivalente a

    totale = totale + x

Man mano che il ciclo lavora, totale accumula la somma degli elementi; una variabile usata in questo modo è detta anche accumulatore.

Sommare gli elementi di una lista è un’operazione talmente comune che Python contiene una apposita funzione predefinita, sum:

>>> t = [1, 2, 3]
>>> sum(t)
6

Una simile operazione che compatta una sequenza di elementi in un singolo valore, è chiamata riduzione.

Talvolta è necessario attraversare una lista per costruirne contemporaneamente un’altra. Per esempio, la funzione seguente prende una lista di stringhe e restituisce una nuova lista che contiene le stesse stringhe in lettere maiuscole:

def tutte_maiuscole(t):
    res = []
    for s in t:
        res.append(s.capitalize())
    return res

res è inizializzata come una lista vuota; ad ogni ripetizione del ciclo viene accodato un elemento. Pertanto res è una sorta di accumulatore.

Un’operazione come quella di tutte_maiuscole è chiamata anche mappa: applica una funzione (in questo caso il metodo capitalize) su ciascun elemento di una sequenza.

Un’altra operazione frequente è la selezione di alcuni elementi di una lista per formare una sottolista. Per esempio, la seguente funzione prende una lista di stringhe e restituisce una lista che contiene solo le stringhe scritte in lettere maiuscole:

def solo_maiuscole(t):
    res = []
    for s in t:
        if s.isupper():
            res.append(s)
    return res

isupper è un metodo delle stringhe che restituisce True se la stringa contiene solo lettere maiuscole.

Un’operazione come quella di solo_maiuscole è chiamata filtro perché seleziona solo alcuni elementi, filtrando gli altri.

La maggior parte delle operazioni sulle liste possono essere espresse come combinazioni di mappa, filtro e riduzione.

10.8  Cancellare elementi

Ci sono alcuni modi per cancellare elementi da una lista. Se conoscete l’indice dell’elemento desiderato, potete usare pop:

>>> t = ['a', 'b', 'c']
>>> x = t.pop(1)
>>> t
['a', 'c']
>>> x
'b'

pop modifica la lista e restituisce l’elemento che è stato rimosso. Se omettete l’indice, il metodo cancella e restituisce l’ultimo elemento della lista.

Se non vi serve il valore rimosso, potete usare l’operatore del:

>>> t = ['a', 'b', 'c']
>>> del t[1]
>>> t
['a', 'c']

Se conoscete l’elemento da rimuovere ma non il suo indice, potete usare remove:

>>> t = ['a', 'b', 'c']
>>> t.remove('b')
>>> t
['a', 'c']

Il valore di ritorno di remove è None.

Per cancellare più di un elemento potete usare del con lo slicing:

>>> t = ['a', 'b', 'c', 'd', 'e', 'f']
>>> del t[1:5]
>>> t
['a', 'f']

Come di consueto, lo slicing seleziona gli elementi fino al secondo indice escluso.

10.9  Liste e stringhe

Una stringa è una sequenza di caratteri e una lista è una sequenza di valori, ma una lista di caratteri non è la stessa cosa di una stringa. Per convertire una stringa in una lista di caratteri, potete usare list:

>>> s = 'spam'
>>> t = list(s)
>>> t
['s', 'p', 'a', 'm']

Poiché list è una funzione predefinita, va evitato di chiamare una variabile con questo nome. Personalmente evito anche l perché somiglia troppo a 1. Ecco perché di solito uso t.

La funzione list separa una stringa in singole lettere. Se invece volete spezzare una stringa nelle singole parole, usate il metodo split:

>>> s = 'profonda nostalgia dei fiordi'
>>> t = s.split()
>>> t
['profonda', 'nostalgia', 'dei', 'fiordi']

Un argomento opzionale chiamato delimitatore specifica quale carattere va considerato come separatore delle parole. L’esempio che segue usa il trattino come separatore:

>>> s = 'spam-spam-spam'
>>> delimita = '-'
>>> t = s.split(delimita)
>>> t
['spam', 'spam', 'spam']

join è l’inverso di split: prende una lista di stringhe e concatena gli elementi. join è un metodo delle stringhe, quindi lo dovete invocare per mezzo del delimitatore e passare la lista come parametro:

>>> t = ['profonda', 'nostalgia', 'dei', 'fiordi']
>>> delimita = ' '
>>> s = delimita.join(t)
>>> s
'profonda nostalgia dei fiordi'

In questo caso il delimitatore è uno spazio, quindi join aggiunge uno spazio tra le parole. Per concatenare delle stringhe senza spazi, basta usare come delimitatore la stringa vuota ''.

10.10  Oggetti e valori

Se eseguiamo queste istruzioni di assegnazione:

a = 'banana'
b = 'banana'

Sappiamo che a e b si riferiscono a una stringa, ma non sappiamo se si riferiscono alla stessa stringa. Ci sono due possibili stati, illustrati in Figura 10.2.


Figure 10.2: Diagramma di stato.

In un caso, a e b si riferiscono a due oggetti diversi che hanno lo stesso valore. Nell’altro, si riferiscono allo stesso oggetto.

Per controllare se due variabili si riferiscono allo stesso oggetto, potete usare l’operatore is.

>>> a = 'banana'
>>> b = 'banana'
>>> a is b
True

In questo esempio, Python ha creato un unico oggetto stringa, e sia a che b fanno riferimento ad esso.

Ma se create due liste, ottenete due oggetti distinti:

>>> a = [1, 2, 3]
>>> b = [1, 2, 3]
>>> a is b
False

Quindi il diagramma di stato somiglia a quello di Figura 10.3.


Figure 10.3: Diagramma di stato.

In quest’ultimo caso si dice che le due liste sono equivalenti, perché contengono gli stessi elementi, ma non identiche, perché non sono lo stesso oggetto. Se due oggetti sono identici, sono anche equivalenti, ma se sono equivalenti non sono necessariamente identici.

Fino ad ora abbiamo usato “oggetto” e “valore” indifferentemente, ma è più preciso dire che un oggetto ha un valore. Se valutate [1,2,3], ottenete un oggetto lista il cui valore è una sequenza di interi. Se un’altra lista contiene gli stessi elementi, diciamo che ha lo stesso valore, ma non che è lo stesso oggetto.

10.11  Alias

Se a si riferisce a un oggetto e assegnate b = a, allora entrambe le variabili si riferiscono allo stesso oggetto.

>>> a = [1, 2, 3]
>>> b = a
>>> b is a
True

Il diagramma di stato è quello in Figura 10.4.


Figure 10.4: Diagramma di stato.

L’associazione tra una variabile e un oggetto è chiamato riferimento. In questo esempio ci sono due riferimenti allo stesso oggetto.

Un oggetto che ha più di un riferimento ha anche più di un nome, e si dice quindi che l’oggetto ha degli alias.

Se l’oggetto munito di alias è mutabile, i cambiamenti provocati da un alias si riflettono anche sull’altro:

>>> b[0] = 42
>>> a
[42, 2, 3]

Sebbene questo comportamento possa essere utile, è anche fonte di errori. In genere è più sicuro evitare gli alias quando si sta lavorando con oggetti mutabili.

Per gli oggetti immutabili come le stringhe, gli alias non sono un problema. In questo esempio:

a = 'banana'
b = 'banana'

Non fa quasi mai differenza se a e b facciano riferimento alla stessa stringa o meno.

10.12  Liste come argomenti

Quando passate una lista a una funzione, questa riceve un riferimento alla lista. Se la funzione modifica la lista, il chiamante vede la modifica. Per esempio, decapita rimuove il primo elemento di una lista:

def decapita(t):
    del t[0]

Vediamo come si usa:

>>> lettere = ['a', 'b', 'c']
>>> decapita(lettere)
>>> lettere
['b', 'c']

Il parametro t e la variabile lettere sono due alias dello stesso oggetto. Il diagramma di stack è riportato in Figura 10.5.


Figure 10.5: Diagramma di stack.

Dato che la lista è condivisa da due frame, la disegno in mezzo.

È importante distinguere tra operazioni che modificano le liste e operazioni che creano nuove liste. Per esempio il metodo append modifica una lista, ma l’operatore + ne crea una nuova.

Ecco un esempio che usa append:

>>> t1 = [1, 2]
>>> t2 = t1.append(3)
>>> t1
[1, 2, 3]
>>> t2
None

Il valore di ritorno di append è None.

Un esempio di utilizzo dell’operatore +:

>>> t3 = t1 + [4]
>>> t1
[1, 2, 3]
>>> t3
[1, 2, 3, 4]

Il risultato è una nuova lista, e la lista di origine resta immutata.

Questa differenza è importante quando scrivete delle funzioni che devono modificare delle liste. Per esempio, questa funzione non cancella il primo elemento della lista:

def non_decapita(t):
    t = t[1:]              # SBAGLIATO!

L’operatore di slicing crea una nuova lista e l’assegnazione fa in modo che t si riferisca ad essa, ma tutto ciò non ha effetti sul chiamante.

>>> t4 = [1, 2, 3]
>>> non_decapita(t4)
>>> t4
[1, 2, 3]

Alla chiamata di non_decapita, t e t4 fanno riferimento alla stessa lista. Alla fine, t fa riferimento ad una nuova lista, mentre t4 continua a fare riferimento alla stessa lista, non modificata.

Un’alternativa valida è scrivere una funzione che crea e restituisce una nuova lista. Per esempio, ritaglia restituisce tutti gli elementi di una lista tranne il primo:

def ritaglia(t):
    return t[1:]

Questa funzione lascia intatta la lista di origine. Ecco come si usa:

>>> lettere = ['a', 'b', 'c']
>>> resto = ritaglia(lettere)
>>> resto
['b', 'c']

10.13  Debug

Un uso poco accurato delle liste (e degli altri oggetti mutabili) può portare a lunghe ore di debug. Ecco alcune delle trappole più comuni e i modi per evitarle:

  1. La maggior parte dei metodi delle liste modificano l’argomento e restituiscono None. È il comportamento opposto dei metodi delle stringhe, che restituiscono una nuova stringa e lasciano immutato l’originale.

    Se siete abituati a scrivere il codice per le stringhe così:

    parola = parola.strip()
    

    Può venire spontaneo di scrivere il codice per le liste così:

    t = t.sort()           # SBAGLIATO!
    

    Ma poiché sort restituisce None, l’operazione successiva che eseguite su t con tutta probabilità fallirà.

    Prima di usare i metodi delle liste e gli operatori, leggetene attentamente la documentazione e fate una prova in modalità interattiva.

  2. Scegliete un costrutto e usate sempre quello.

    Una parte dei problemi delle liste deriva dal fatto che ci sono molti modi per fare le cose. Per esempio, per rimuovere un elemento da una lista potete usare pop, remove, del, oppure lo slicing.

    Per aggiungere un elemento potete usare il metodo append o l’operatore +. Supponendo che t sia una lista e x un elemento, le espressioni seguenti vanno entrambe bene:

    t.append(x)
    t = t + [x]
    

    Mentre queste sono sbagliate:

    t.append([x])          # SBAGLIATO!
    t = t.append(x)        # SBAGLIATO!
    t + [x]                # SBAGLIATO!
    t = t + x              # SBAGLIATO!
    

    Provate ognuno di questi esempi in modalità interattiva per verificare quello che fanno. Noterete che solo l’ultima espressione causa un errore di esecuzione; le altre sono consentite, ma fanno la cosa sbagliata.

  3. Fate copie per evitare gli alias.

    Se volete usare un metodo come sort che modifica l’argomento, ma anche mantenere inalterata la lista di origine, potete farne una copia.

    >>> t = [3, 1, 2]
    >>> t2 = t[:]
    >>> t2.sort()
    >>> t
    [3, 1, 2]
    >>> t2
    [1, 2, 3]
    

    In questo esempio, si può anche usare la funzione predefinita sorted, che restituisce una nuova lista ordinata e lascia intatta quella di origine.

    >>> t2 = sorted(t)
    >>> t
    [3, 1, 2]
    >>> t2
    [1, 2, 3]
    

10.14  Glossario

lista:
Una sequenza di valori.
elemento:
Uno dei valori in una lista (o in altri tipi di sequenza).
lista nidificata:
Lista che è contenuta come elemento in un’altra lista.
accumulatore:
Variabile usata in un ciclo per sommare cumulativamente un risultato.
assegnazione potenziata:
Istruzione che aggiorna un valore di una variabile usando un operatore come +=.
riduzione:
Schema di elaborazione che attraversa una sequenza e ne accumula gli elementi in un singolo risultato.
mappa:
Schema di elaborazione che attraversa una sequenza ed esegue una stessa operazione su ciascun elemento della sequenza.
filtro:
Schema di elaborazione che attraversa una lista e seleziona solo gli elementi che soddisfano un dato criterio.
oggetto:
Qualcosa a cui una variabile può fare riferimento. Un oggetto ha un tipo e un valore.
equivalente:
Avente lo stesso valore.
identico:
Essere lo stesso oggetto (implica anche l’equivalenza).
riferimento:
L’associazione tra una variabile e il suo valore.
alias:
Due o più variabili che si riferiscono allo stesso oggetto, con nomi diversi.
delimitatore:
Carattere o stringa usato per indicare i punti dove una stringa deve essere spezzata.

10.15  Esercizi

Potete scaricare le soluzioni degli esercizi seguenti all’indirizzo http://thinkpython2.com/code/list_exercises.py.


Esercizio 1  

Scrivete una funzione di nome somma_nidificata che prenda una lista di liste di numeri interi e sommi gli elementi di tutte le liste nidificate. Esempio:

>>> t = [[1, 2], [3], [4, 5, 6]]
>>> somma_nidificata(t)
21


Esercizio 2  

Scrivete una funzione di nome somma_cumulata che prenda una lista di numeri e restituisca la somma cumulata, cioè una nuova lista dove l’i-esimo elemento è la somma dei primi i+1 elementi della lista di origine. Per esempio:

>>> t = [1, 2, 3]
>>> somma_cumulata(t)
[1, 3, 6]


Esercizio 3  

Scrivete una funzione di nome mediani che prenda una lista e restituisca una nuova lista che contenga tutti gli elementi, esclusi il primo e l’ultimo. Esempio:

>>> t = [1, 2, 3, 4]
>>> mediani(t)
[2, 3]


Esercizio 4  

Scrivete una funzione di nome tronca che prenda una lista, la modifichi togliendo il primo e l’ultimo elemento, e restituisca None. Esempio:

>>> t = [1, 2, 3, 4]
>>> tronca(t)
>>> t
[2, 3]


Esercizio 5   Scrivete una funzione di nome ordinata che prenda una lista come parametro e restituisca True se la lista è ordinata in senso crescente, False altrimenti. Esempio:
>>> ordinata([1, 2, 2])
True
>>> ordinata(['b', 'a'])
False


Esercizio 6  

Due parole sono anagrammi se potete ottenerle riordinando le lettere di cui sono composte. Scrivete una funzione di nome anagramma che riceva due stringhe e restituisca True se sono anagrammi.


Esercizio 7  

Scrivete una funzione di nome ha_duplicati che richieda una lista e restituisca True se contiene elementi che compaiono più di una volta. Non deve modificare la lista di origine.


Esercizio 8  

Questo è un esercizio sul cosiddetto “Paradosso del compleanno”; potete approfondirlo leggendo http://it.wikipedia.org/wiki/Paradosso_del_compleanno.

Se in una classe ci sono 23 studenti, quante probabilità ci sono che due di loro compiano gli anni lo stesso giorno? Potete stimare questa probabilità generando alcuni campioni a caso di 23 date e controllando le corrispondenze. Suggerimento: per generare date in modo casuale usate la funzione randint nel modulo random.

Potete scaricare la mia soluzione da http://thinkpython2.com/code/birthday.py.


Esercizio 9  

Scrivete una funzione che legga il file words.txt e crei una lista in cui ogni parola è un elemento. Scrivete due versioni della funzione, una che usi il metodo append e una il costrutto t = t + [x]. Quale richiede più tempo di esecuzione? Perché?

Soluzione: http://thinkpython2.com/code/wordlist.py.


Esercizio 10  

Per controllare se una parola è contenuta in un elenco, è possibile usare l’operatore in, ma è un metodo lento, perché ricerca le parole seguendo il loro ordine.

Dato che le parole sono in ordine alfabetico, possiamo accelerare l’operazione con una ricerca binaria (o per bisezione), che è un po’ come cercare una parola nel vocabolario. Partite nel mezzo e controllate se la parola che cercate viene prima o dopo la parola di metà elenco. Se prima, cercherete nella prima metà nello stesso modo, se dopo, cercherete nella seconda metà.

Ad ogni passaggio, dimezzate lo spazio di ricerca. Se l’elenco ha 113.809 parole, ci vorranno circa 17 passaggi per trovare la parola o concludere che non c’è.

Scrivete una funzione di nome bisezione che richieda una lista ordinata e un valore da ricercare, e restituisca l’indice di quel valore, se fa parte della lista, oppure None se non esiste.

Oppure, potete leggere la documentazione del modulo bisect e usare quello! Soluzione: http://thinkpython2.com/code/inlist.py.


Esercizio 11  

Una coppia di parole è “bifronte” se l’una si legge nel verso opposto dell’altra. Scrivete un programma che trovi tutte le parole bifronti nella lista di parole. Soluzione: http://thinkpython2.com/code/reverse_pair.py.


Esercizio 12  

Due parole si “incastrano” se, prendendo le loro lettere alternativamente dall’una e dall’altra, si forma una nuova parola. Per esempio, le parole inglesi “shoe” and “cold” incastrandosi formano “schooled”.

  1. Scrivete un programma che trovi tutte le coppie di parole che possono incastrarsi. Suggerimento: non elaborate tutte le coppie!
  2. Riuscite a trovare dei gruppi di tre parole che possono incastrarsi tra loro? Cioè, tre parole da cui, prendendo le lettere una ad una alternativamente, nell’ordine, si formi una nuova parola? (Es. “ace”, “bus” e “as” danno “abacuses”)

Soluzione: http://thinkpython2.com/code/interlock.py. Fonte: Questo esercizio è tratto da un esempio di http://puzzlers.org.

Buy this book at Amazon.com

Contribute

If you would like to make a contribution to support my books, you can use the button below. Thank you!
Pay what you want:

Are you using one of our books in a class?

We'd like to know about it. Please consider filling out this short survey.



Previous Up Next