domingo, 25 de outubro de 2009

Problema 4.16

Por definição os netos são os filhos dos filhos. Usando o princípio da programação descendente, por camadas de abstracção, admitamos que sabemos com determinar os filhos de alguém. então uma solução para o nosso problema pode ser facilmente equacionada:


def netos(dicio,progenitor):
""" Lista netos."""
desc1 = filhos(dicio,progenitor)
if desc1:
net = []
for elem in desc1:
desc2 = filhos(dicio,elem)
if desc2:
net = net + desc2
else:
return []
return net


Na linha 3, calculamos os filhos. Como o faremos em concreto depois se verá. Para ter netos é preciso que o progenitor tenha ... filhos (teste na linha 4)! Caso tenha, usamos o padrão acumulador para determinar os filhos de cada filho e juntar tudo numa lista chamada net (linhas 5 a 9). Passemos então ao problema de saber quem são os filhos de alguém. Questão fácil dada a organização do dicionário.


def filhos(dicio,progenitor):
""" lista dos filhos."""
res= dicio.get(progenitor,None)
return res


Resolvido o problema pensemos um pouco mais. Não seria interessante uma solução que seguisse de perto a definição? Claro que sim. Algo como:


def netos(dicio ,progenitor):
""" Lista dos netos."""
netos = filhos(dicio,filhos(dicio,progenitor))
return netos


Mas não funcionaria. Porquê? Bem, um olhar atento diz-nos porquê: a função filhos recebe uma cadeia de caracteres (um nome) e devolve uma lista (a lista dos filhos). Assim, na segunda vez que se utilizasse filhos daria erro pois estava a ser tentado executar a definição com um argumento lista em vez de uma cadeia de caracteres. A solução passa por fazer com que a definição filhos funcione com listas de cadeias de caracteres. Este é um exemplo de outro mecanismo importante para resolver problemas: generalização!


def filhos(dicio,lista_progenitores):
lista_filhos = []
for filho in lista_progenitores:
lista_filhos.extend(dicio.get(filho,[]))
return lista_filhos


Notar o uso do método extend, pois agora vamos acumular numa lista elementos que, também eles aparecem em listas. Notar também a necessidade de usar a lista vazia como default do get. O leitor atento dirá: mas agora deixa de funcionar a definição de netos pois no início só há um progenitor!! Mas isso resolve-se facilmente: a primeira chamada de filhos, dentro da chamada de netos tem como segundo argumento uma lista com um elemento: o progenitor. E chegamos à versão completa.


def netos(dicio ,progenitor):
""" Lista dos netos."""
netos = filhos(dicio,filhos(dicio,[progenitor]))
return netos

def filhos(dicio,lista_progenitores):
lista_filhos = []
for filho in lista_progenitores:
lista_filhos.extend(dicio.get(filho,[]))
return lista_filhos

2 comentários:

  1. seria possível esta resolução, tendo em conta a função filhos dada no enunciado:

    def netos(dicio,progenitor):
    '''Lista dos netos.'''
    fim=list()
    filho=filhos(dicio,progenitor)
    for i in filho:
    neto=dicio.get(i,None)
    fim=fim+neto
    return fim

    ResponderEliminar
  2. Goreti:

    Está quase perfeito! A única questão é que tem que usar:

    neto = dicio.get(i, [])

    e não None. Isto porque, no caso de não haver neto o programa ia tentar concatenar uma cadeia de caracteres com None o que daria erro.

    ResponderEliminar