sábado, 19 de outubro de 2013

Problema 3.10

Vamos resolver o problema 3.10 do livro que nos pede para gerar uma cadeia de ADN. O único argumento/parâmetro formal é o tamanho da sequência pretendido. Trata-se de um exercício muito fácil, mas que nos pode dar alguns ensinamentos.
A ideia da solução passa por repetir tantas vezes quantas o tamanho da sequência a escolha aleatória de uma das bases presentes na cadeia de ADN, de entre as quatro possíveis (Adenina (A), Citosina (C), Guanina (G) e Timina (T). Os resultados vão sendo acumulados. Daí a solução.
import random

def gera_adn(tam):
    """Gera uma cadeia de ADN de tamanho tam. Padrão ciclo-acumulador"""
    adn =''
    for i in range(tam):
        base = random.choice('TACG')
        adn = adn + base
    return adn
Baseia-se esta solução no padrão ciclo (neste caso ciclo for) e acumulador (o nome adn onde vamos acumulando os resultados).
Suponhamos agora uma situação semelhante. Alguém anda perdido numa cidade, perfeitamente geométrica, e pede ajuda para se deslocar a um dado local da cidade. Recebe ajuda na forma de uma sequência de indicações do tipo Avança (A), Recua (R), Vira à Esquerda (E) ou Vira à Direita (D). Admitamos que o que se pretende é um programa que gere sequências válidas de indicações, de tamanho variável. O leitor não estranhará, depois de uma breve reflexão, que a solução proposta não lhe ofereça grandes dúvidas.
mport random
import random
def gera_comandos(tam):
    """
    Gera uma sequências de indicações de movimento numa cidade de tamanho tam.
    Padrão ciclo-acumulador
    """
    seq_comandos =''
    for i in range(tam):
        comando = random.choice('ARED')
        seq_comandos = seq_comandos + comando
    return seq_comandos
Olhando para estas soluções verificamos que o que as distingue é apenas os caracteres possíveis nos dois casos. Podemos então abstrair esse detalhe, e construir uma solução genérica que sirva para gerar qualquer sequência de caracteres, conhecido o alfabeto dos caracteres possíveis. Vamos a isso.
import random

def gera_comandos(tamanho, alfabeto):
    """ Gera uma sequência de comandos com elementos retirados aleatoriamente do alfabeto."""
    comandos = ''
    for i in range(tamanho):
        comandos = comandos + random.choice(alfabeto)
    return comandos
Mais uma vez verificamos que generalizar significa transformar uma constante (no caso a cadeia de ADN ou de indicações) num nome que aparece como parâmetro formal. Mas será que as versões concretas devem ser deitadas fora? Não necessariamente. Suponha que tem indicações sobre a probabilidade de ocorrência de um dos eventos. Como incorporar isso no programa. Vamos ver para o caso da indicação do percurso. Se a pessoa for competente então é provável que dê mais indicações de Avançar do que de Recuar e que privilegie também uma das indicações de Virar. Vamos ver como podemos incorporar essa indicação no código.
import random

def gera_comandos(n):
    """Gera n comandos aleatoriamente. Alguns movimentos são mais prováveis do que outros."""
    comandos = ''
    for i in range(n):
        if random.choice([0,0,0,1]) == 0:
            comandos += random.choice(['A','A', 'A','A','R'])
        else:
            comandos += random.choice(['E',’E’, 'D'])
    return comandos
Neste exemplo, avançar e recuar globalmente têm 75% de probabilidades de ocorrer, enquanto virar tem apenas 25%. Dentro de cada caso também há diferenças: avançar tem 80% de probabilidade de ocorrer e virar à esquerda 66%.

Sem comentários:

Enviar um comentário