segunda-feira, 18 de novembro de 2013

Amigos, Amigos,...

Um dos problemas do livro (problema 5.8) fala-nos de palavras amigas. Elas são amigas se o número de posições em que os respectivos caracteres difere for inferior a 10%. A propósito deste problema um aluno de IPRP enviou-me o seguinte email (de que reproduzo a parte substantiva).

“Para comparar caractere a caractere estou a utilizar um ciclo for: ....... for car in cad1:         if cad1[car] != cad2[car] ........ ou seja vou comparar os carateres de cada cadeia na mesma posição e ver se eles são diferentes o python diz-me que o que esta dentro de cad1 e cad2 tem de ser um numero inteiro tendo o meu código dado erro.”

Qual é o problema? A resposta remete para os dois modos de percorrer um ciclo for: por posição ou por conteúdo. No caso do aluno ele está a fazer uma travessia do ciclo por conteúdo:
for car in cad1:
Depois no teste usa a operação de indexação, que permite aceder ao conteúdo mas por posição! Por isso o erro de dizer que o índice tem que ser um inteiro. A solução passa por fazer a travessia por posição:
for i in range(len(cad1)):
   if cad1[i] != cad2[i]
Já agora o programa completo.
def amigas(cad_1, cad_2):
    """palavras que diferem em menos de 10% dizem-se amigas. Assume igual comprimento"""
    # Calcula distancia
    diferem = 0 
    for i in range(len(cad_1)):
        if cad_1[i] != cad_2[i]:
            diferem += 1
    percentagem = diferem / len(cad_1)
    return percentagem < 0.1
Este programa funciona para qualquer tipo de sequências: cadeias de caracteres, tuplos e listas. O curioso da questão é que a versão do aluno podia correr sem dar erro caso se use um tuplo (ou uma lista) formado(a) por inteiros que correspondam a índices válidos dessas sequências! Se não acredita experimente:
def amigas(cad_1, cad_2):
    """palavras que diferem em menos de 10% dizem-se amigas. Assume igual comprimento"""
    # Calcula distancia
    diferem = 0 
    for car in cad_1:
        if cad_1[car] != cad_2[car]:
            diferem += 1
    percentagem = diferem / len(cad_1)
    return percentagem < 0.1

if __name__ == '__main__':
    c1 = [0,1,2,3,4,5,6,7,8,9,0,1,3,3,4,5,6,7,8,9,0]
    c2 = [0,1,4,3,4,5,6,7,8,9,0,1,3,3,4,5,6,7,8,9,0]
    c3 = (0,1,2,3,4)
    c4 = (4,3,2,1,0)
    print(amigas(c1,c2))
    print(amigas(c3,c4))
Moral desta última parte da história: muitas vezes os programas funcionam para certos valores dos parâmetros reais e parece que está tudo bem... quando não está.

Sem comentários:

Enviar um comentário