domingo, 30 de outubro de 2011

Problema 4.6

Este problema obriga a alguns cuidados. Mas também é um pretexto para percebermos como podemos construir um programa por aproximações sucessivas, não tentando resolver tudo de uma só vez.

De acordo com o algoritmo dado no enunciado uma solução possível para o nosso problema poderá ser:

def cria_chave(palavra_chave):
"""Gera uma chave a partir de uma palavra de passe."""
alfabeto = 'abcdefghijklmnopqrstuvwxyz '
# retira duplicações da palavra chave
palavra_chave = retira_dup(palavra_chave)
# divide em duas partes
ultimo_car = palavra_chave[-1]
indice = alfabeto.find(ultimo_car)
antes = alfabeto[:indice]
depois = alfabeto[indice+1:]
# retira caracteres da palavra chave
antes = retira_car(palavra_chave, antes)
depois = retira_car(palavra_chave, depois)
# junta tudo
chave = palavra_chave + depois + antes
return chave

Se olharmos para os comentários torna-se claro que o algoritmo foi correctamente implementado. Claro, que isto só é verdade se as duas funções auxiliares, retira_dup e retira_car, funcionarem bem. É disso que vamos agora tratar. Comecemos pelo problema de retirar os duplicados.

def retira_dup(cadeia):
"""Retira caracteres duplicados na cadeia."""
nova_cadeia = ''
for car in cadeia:
if car not in nova_cadeia:
nova_cadeia = nova_cadeia + car
return nova_cadeia

Esta solução, constrói uma nova cadeia, percorrendo os elementos da cadeia antiga uma a um, e só introduzindo os caracteres caso não provoquem uma duplicação.

Uma alternativa é o programa seguinte.

def retira_dup_2(cadeia):
"""Retira caracteres duplicados na cadeia."""
nova_cadeia = ''
for ind, car in enumerate(cadeia):
if car not in cadeia[ind+1:]:
nova_cadeia = nova_cadeia + car
return nova_cadeia

Aqui fazemos uso da função enumerate que nos permite percorrer a cadeia simultaneamente pela índices e pelo conteúdo. Veja-se como no teste dentro do if determinamos se um caractere é ou não repetido.

Agora a parte de retirar carateres de um texto.

def retira_car(caracteres, texto):
"""retira do texto os caracteres."""
novo_texto = ''
for car in texto:
if car not in caracteres:
novo_texto = novo_texto + car
return novo_texto

Ainda e sempre a mesma ideia: percorrer o texto (ciclo), e sempre que o caractere em análise não pertencer aos caracteres proibidos ele é adicionado (acumulador). A contagem é implícita.

A lição que podemos tirar deste exemplo é a de que vale a pena usar mecanismos de abstracção (neste caso as duas funções auxiliares) para melhor dominar a complexidade da busca da solução para o nosso problema.

Sem comentários:

Enviar um comentário