segunda-feira, 21 de outubro de 2013

Erros, equívocos e outras singularidades (I)

Depois de corrigir testes e/ou exames tenho por hábito, com mais calma, olhar para as vossas respostas na procura dos problemas que ainda subsistem. Todos aprendem com os erros, mesmo com os erros dos outros. No caso dos docentes isso serve para procurar melhorar o modo como ensinam. Vou tentar referir aqui no blogue algumas das situações que nos podem ajudar a ser melhores programadores. Começo com o problema do teste da TP9 que pedia para calcular a Distância de Hamming entre duas cadeias de caracteres, isto é, o número de posições em que os caracteres das duas cadeias são diferentes. Vejamos uma das soluções que apresentaram. Trata-se de uma solução muito próxima da melhor solução.
def dist_ham(cad_1, cad_2):
    res = 0
    indice = 0
    if len(cad_1) > len(cad_2):
        return False
    for car in cad_1:
        if car != cad_2[indice]:
            res = res + 1
        indice = indice + 1
    return res
Este programa funciona para cadeias de igual comprimento. Mas o que acontece se a segunda cadeia for maior do que a primeira? Com esta solução, entra no ciclo na mesma quando me parece que a ideia era a de que não fosse assim: @ autor@ queria dizer que se fossem diferentes então devia dar False. Então, uma primeira correcção seria:
def dist_ham(cad_1, cad_2):
    res = 0
    indice = 0
    if len(cad_1) != len(cad_2):
        return False
    for car in cad_1:
        if car != cad_2[indice]:
            res = res + 1
        indice = indice + 1
    return res
Claro que, o que o enunciado pedia implicitamente era para tratar também esse caso, considerando que os caracteres em excesso também deviam ser contados como diferentes. Mas vamos esquecer esse detalhe e olhar para outro aspecto do código menos conseguido.

Nas aulas foi referido que num ciclo for as sequências podem percorridas por posição/índice ou por conteúdo. A opção depende do problema. No exemplo acima estão a ser usadas ambas! É evidente que temos que comparar caracteres e esse facto pode levar a pensar em percorrer as cadeias por conteúdo. Mas temos que comparar os caracteres de cada cadeia numa dada posição. E isso obriga a cada momento qual a posição dos caracteres que queremos comparar. Neste caso, é esta situação que deve prevalecer. Daí a nova versão:
def dist_ham(cad_1, cad_2):
    res = 0

    if len(cad_1) != len(cad_2):
        return False
    for indice in range(len(cad_1)):
        if cad_1[indice] != cad_2[indice]:
            res = res + 1
    return res
Uma vez mais, a solução acima não responde satisfatoriamente no caso das cadeias de comprimento diferente. Em post anterior já mostrei como se podia resolver o problema, mesmo quando as cadeias têm comprimentos diferentes.
Conclusão maior: não é boa prática misturar duas formas de percorrer uma sequência. Mas se tal for mesmo necessário há um modo Pythoniano de o fazer recorrendo à função enumerate. Exemplo:
>>> cadeia = 'abcdef'
>>> for indice, valor in enumerate(cadeia): # <-- enumerate!!
... print('indice %d:\tcaractere= %s' % (indice, valor))
...
indice 0: caractere=  a
indice 1: caractere= b
indice 2: caractere= c
indice 3: caractere= d
indice 4: caractere= e
indice 5: caractere= f
That’s it!

Sem comentários:

Enviar um comentário