domingo, 29 de novembro de 2015

Árvore Genealógica

No texto de apoio à disciplina é introduzido um conceito simplista de árvore genealógica. Estas árvores são representadas por um dicionário em que as chaves são nomes de pessoas (um progenitor) e os valores são listas de nomes de pessoas (os filhos). Esta representação permite, por exemplo, obter os filhos de alguém de modo trivial:
def filhos(dicio,progenitor):
    """ lista dos filhos."""
    return dicio.get(progenitor,[])
Também é fácil listar os netos de alguém. Por exemplo:
def netos(dicio,progenitor):
    """ Lista netos. Filhos dos filhos"""
    desc1 = filhos(dicio,progenitor)
    if desc1:
        net = []
        for elem in desc1:
            desc2 = filhos(dicio,elem)
            if desc2:
                net = net + desc2
        return net
    else:
        return []
Esta solução calcula primeiro os filhos e, caso existam, os filhos dos filhos. Não é difícil propor versões alternativas para esta questão. Por exemplo:
def netos_b(arv_genea,progenitor):
    net = []
    desc1 = filhos(arv_genea,progenitor)
    for prog in desc1:
        net.extend(filhos(arv_genea,prog))
    return net
Aqui simplificamos o código no interior do ciclo recorrendo ao método extend. Mas ainda podemos aproximarmo-nos mais da defino natural: netos são os filhos dos filhos:
def netos_b(dicio ,progenitor):
    """ Lista dos netos. Os filhos dos filhos"""
    return filhos_b(dicio,filhos_b(dicio,[progenitor]))

def filhos_b(dicio,lista_progenitores):
    lista_filhos = []
    for filho in lista_progenitores:
        lista_filhos.extend(dicio.get(filho,[]))
    return lista_filhos
Note-se que tivemos que alterar a função filhos para agora me dar a lista dos filhos de um conjunto de pessoas.
Agora o conceito básico de progenitor de alguém:
def progenitor(ag,nome):
    for p,fil in ag.items():
        if nome in fil:
            return p
    return None
Neste caso vamos procurar o nome na lista dos filhos de alguém que, a existir, será o progenitor. Passemos a outros exemplos. Irmãos são pessoas que têm um progenitor comum. Com está organizada a árvore genealógica cada pessoa tem um progenitor único, logo:
def irmaos(ag,nome1,nome2):
    """ Têm o mesmo progenitor?"""
    prog1 = progenitor(ag, nome1)
    prog2 = progenitor (ag,nome2)
    return prog1 == prog2
Socorrendo-nos de novo da ideia de progenitor podemos definir o conceito de avô/avó.
def avo(dic,nome):
    """ Quem é o avô/avó do nome."""
    prog = progenitor(dic,nome)
    if prog:
        return progenitor(dic,prog)
    return None
Deixamos ao leitor o cuidado de definir outras relações de parentesco. Por exemplo, tente o conceito de primos (os filhos de irmãos). Por outro lado, alguns dos conceitos acima são booleanos. Imagine que em vez de se saber se duas pessoas são primos se pretende saber quais os primos de alguém. Não lhe deve ser difícil chegar à solução.
Finalmente, pense numa implementação mais realista de uma árvore genealógica, em que cada pessoa tem associado os seus pais. E faça tudo de novo!!!

Sem comentários:

Enviar um comentário