domingo, 10 de janeiro de 2016

Teste Final - Pergunta 4

Era pedido um programa em que se somam dois vectores esparsos representados através de dicionários. Um vector esparso é aquele em que a esmagadora maioria dos seus elementos é zero. Usando um dicionário apenas representamos explicitamente os casos diferentes de zero, poupando muito espaço e salvando tempo nas operações. Por exemplo, o vector x = (0,0,0,2,0,0,0,5,0,0) pode ser representado, com economia, pelo dicionário d ={3:2, 7:5, ‘len’:10}. Notar a referência ao comprimento, um parâmetro importante da representação.

Das respostas dadas no teste, quase todos(as) optaram por transformar os dois vectores representados por dicionários em listas, seguido da soma das duas listas, par finalmente depois construir o dicionário resultado. Se pensarmos um pouco, isto é tudo menos boa programação, porque precisamente destrói o que se ganha em usar uma representação baseada em dicionários: espaço e tempo! Mesmo assim, as soluções apresentadas têm muitas deficiências (por exemplo, recurso errado a isdigit() ou a type(x) == int, em vez de isinstance(x,int)). Eis uma solução possível para essa abordagem.
def soma_vec_esparso_b(vec_1, vec_2):
    comp = vec_1['len']
    # Converte dicionários em listas
    list_1 = [vec_1.get(i,0) for  i in range(comp) ]
    list_2 = [vec_2.get(i,0) for  i in range(comp)]
    # soma listas
    list = [list_1[i] + list_2[i] for i in range(comp)]
    # constrói dicionário
    dic = {i: list[i] for i in range(comp) if list[i] > 0}
    dic['len'] = comp
    return dic
Fazemos uso de listas e dicionários por compreensão, que nos permite um código curto.Claro que podem ser substituídas por ciclos normais.

Então qual seria a solução baseada em dicionários? Como vão ver, simples e curta.
def soma_vec_esparso(vec_1, vec_2):
    vec_3 = {}
    vec_3.update(vec_2)
    for ch1,val1 in vec_1.items():
        if ch1 != 'len': # isinstance(ch1,int)
            vec_3[ch1] = val1 + vec_3.get(ch1,0)
    return vec_3
A ideia é começar por copiar um dos dicionários para a solução usando o método update ( isso inclui a chave ‘len’), e depois verificar os elementos relevantes (isto é, diferentes de ‘len’) do outro vector efectuando a soma. Em comentário, mostramos que podemos fazer o teste para saber se é ‘len’ ou um número de um modo mais geral.