Animals híbrids

../../../_images/Vacamell.png

Un dels animals híbrids, el vacamell

Una missió espacial ha trobat vida extraterrestre en un planeta remot. Meravellats per la gran varietat de nous animals que han descobert, els biòlegs de la terra es troben ara amb el problema d’haver de donar nom a les noves espècies. Com que aquestes bèsties extraterrestres semblen híbrids d’animals terrícoles, decideixen batejar-les amb noms compostos d’animals coneguts. Per exemple, d’un resistent animal blanc i negre, geperut i amb banyes que habita al desert en diuen vacamell (mig vaca, mig camell); a l’animal amb closca que lentament va construint preses als rius decideixen dir-li castortuga (mig castor, mig tortuga); etc. Atesa l’altíssima biodiversitat del planeta, els biòlegs s’adonen que seria molt útil disposar d’una llista de noms compostos per poder-la fer servir cada cop que descobreixin una nova espècie.

Per això us demanen ajut a vosaltres. El seu encàrrec és que dissenyeu un programa que, a partir d’un fitxer que conté noms d’animals, generi tots els noms compostos possibles.

Deseu totes les funcions que se us demanen en el fitxer animalshibrids.py.

Iterador sobre un conjunt de noms

En primer lloc, es demana que escriviu la funció generadora següent:

animalshibrids.iter_noms(nf)

Genera un iterador sobre el conjunt de noms d’animals que hi ha al fitxer de nom nf, el qual conté diversos noms d’animals, en una o diverses línies. Dins d’una mateixa línia, els noms d’animals estan separats per un o més espais en blanc.

Per exemple, si el contingut del fitxer animals.txt és aquest:

vaca camell cabra elefant tortuga gat
castor tapir piranya aranya
mallerenga serp porc camaleo lleo orangutan

la funció iter_noms ha de respondre així:

>>> from animalshibrids import iter_noms
>>> a = iter_noms("animals.txt")
>>> next(a)
'vaca'
>>> next(a)
'camell'
>>> for nom in a:
...    print(nom, end=" ")
... 
cabra elefant tortuga gat castor tapir piranya aranya mallerenga serp porc camaleo lleo orangutan 
>>> next(a)
Traceback (most recent call last):
...
StopIteration

Disposeu de més jocs de proves al fitxer animalshibrids-iternoms.txt.

Composició de dos noms

En segon lloc, escriviu la funció següent:

animalshibrids.composa2noms(nom1, nom2)

Donats dos noms d’animals, retorna el nom compost a partir d’ells o bé l’string buit si el nom no es pot formar.

Les regles per formar un nom compost a partir del nom de dos animals nom1 i nom2 indiquen que:

  • El nom compost és vàlid només si una o més lletres del final de nom1 coincideixen amb les primeres lletres de nom2. Si no en coincideix cap, no es forma nom compost. Per exemple, «rata» i «serp» no formen un nom compost, però en canvi «gos» i «serp» sí («goserp»).

  • Si el final de nom1 coincideix totalment amb nom2, aquesta combinació no és vàlida com a nom compost, ja que no seria un nom d’animal nou. Per exemple, «miloca» i «oca» no generen cap nom compost.

  • No és el mateix el nom compost format a partir de nom1 i nom2 que el format per nom2 i nom1. Per exemple, a partir de «gat» i «tortuga» podem formar tant «gatortuga» com «tortugat».

  • Un nom compost no es pot formar a partir de dues vegades el mateix nom, és a dir, cal que nom1 i nom2 siguin paraules diferents («abellabella» no és vàlid com a nom compost).

  • Quan hi hagi més d’una possibilitat de formar un nom compost, ens quedarem amb aquell cas en què hi hagi un major nombre de lletres coincidents. Per exemple, a partir de «estreptococ» i «cocodril» formem «estreptococodril» (i no «estreptocococodril»).

Per tant, la funció composa2noms ha de respondre així:


>>> from animalshibrids import composa2noms

>>> composa2noms("gos", "serp")
'goserp'
>>> composa2noms("rata", "serp")
''
>>> composa2noms("miloca", "oca")
''
>>> composa2noms("tortuga", "gat")
'tortugat'
>>> composa2noms("gat", "tortuga")
'gatortuga'
>>> composa2noms("bonobo", "bonobo")
''
>>> composa2noms("estreptococ", "cocodril")
'estreptococodril'

Disposeu de més jocs de proves al fitxer animalshibrids-composa2noms.txt.

Generació de tots els noms compostos

Finalment, escriviu la funció

animalshibrids.genera_noms_compostos(it)

Donat un iterador sobre una seqüència de noms d’animals (strings), retorna un altre iterador sobre tots els possibles noms compostos que es poden formar a partir dels noms de it. L’ordre en què es generen els noms compostos és indiferent.

Per exemple,

>>> from animalshibrids import genera_noms_compostos

>>> it1 = iter(['vaca', 'cavall', 'llebre', ])
>>> itn1 = genera_noms_compostos(it1)
>>> sorted(itn1)
['cavallebre', 'vacavall']

>>> it2 = iter(['camell', 'vaca', 'cucut','cuc','cacatua'])
>>> sorted(genera_noms_compostos(it2))
['cucacatua', 'cucamell', 'cucucut', 'vacacatua', 'vacamell']

>>> it3 = iter(['vaca', 'camell', 'cabra', 'elefant', 'tortuga',
... 'gat', 'castor', 'tapir', 'piranya', 'aranya', 'mallerenga', 'serp',
... 'porc', 'camaleo', 'lleo', 'orangutan', 'abella'])
>>> sorted(genera_noms_compostos(it3))
['abellaranya', 'aranyabella', 'cabrabella', 'cabraranya', 'camaleorangutan', 'camelleo', 'castorangutan', 'castortuga', 'elefantapir', 'elefantortuga', 'gatapir', 'gatortuga', 'lleorangutan', 'mallerengabella', 'mallerengaranya', 'mallerengat', 'piranyabella', 'piranyaranya', 'porcabra', 'porcamaleo', 'porcamell', 'porcastor', 'serpiranya', 'serporc', 'tapiranya', 'tortugabella', 'tortugaranya', 'tortugat', 'vacabella', 'vacabra', 'vacamaleo', 'vacamell', 'vacaranya', 'vacastor']

Resoleu aquest apartat sense utilitzar for ni while, sinó només les funcions predefinides de Python 3 que treballen amb iteradors o iterables i les eines del mòdul itertools. En aquest cas, es recomana fer servir itertools.product(), itertools.starmap() i filter().

Disposeu de més jocs de proves al fitxer animalshibrids-generanoms.txt.

Solució

Disposeu d’una solució al fitxer animalshibrids.py.