Python - Ejercicios resueltos con secuencias de ADN y cadenas

Python – Ejercicios resueltos con secuencias de ADN

Hoy vamos a ver más ejercicios de Python con secuencias de ADN. Son 9 ejercicios y se trabaja con cadenas, bases y secuencias.

La descripción dice así:

  1. Desarrollar un programa en Python para usar distintas funciones. El programa debe ofrecer un menú.
  2. Al comienzo del programa preguntar si se desea ingresar una secuencia particular en cada opción correspondiente del menú o si se desea trabajar todo el programa con una misma secuencia fija, que se cargará inicialmente.
  3. En todos los casos se debe controlar que las secuencias ingresadas sean válidas (contengan exclusivamente “A”, “C”, “T”, “G”, y largo de la secuencia mayor o igual a 1) sin importar mayúsculas y minúsculas.

Luego se muestra el menú con estas opciones:

  • Opción 0: Salir del programa
  • Opción 1-9: En cada opción, según se haya indicado inicialmente, se trabaja con la secuencia fija o se solicita una al usuario si corresponde.

En caso de ser necesarios datos adicionales específicos, se solicitan. En cada opción se invoca a la función correspondiente que se detalla a continuación y se muestra el resultado por pantalla.

Python – Secuencias de ADN

A continuación colocaré los 9 puntos que se solicitan y luego el código:

1. transformar_ADN_ARN(secuencia): retorna la transformación de la secuencia de ADN en ARN (cambiando la base “T” por “U”).

Ejemplo: Recibe: “AGGTCT”, retorna: “AGGUCU”.

2. tieneStartStop(secuencia): retorna verdadero si la secuencia empieza con “ATG” y termina con stop: “TGA” y además, entre ambas debe haber una cantidad múltiplo de 3 de bases. No puede contener otras secuencias “ATG” o “TGA”.

Ejemplo: Recibe: “ATGCCAATTTGA”, retorna true. Recibe: “ATACCA”, retorna false.

3. mostrar(secuencia): considerar las bases “A”, “C”, “T” y “G”, retornar la información de cada una de ellas, indicando la cantidad presente en la secuencia (representándola con la misma cantidad de “*””) y el % correspondiente.

Ejemplo: Recibe: “TAAACAACCT”, retorna: A ***** 50.0% C *** 30.0% T ** 20.0% G 0.0%

4. resumir(secuencia): retorna la secuencia en forma resumida, indicando por cada base de la secuencia la cantidad de veces que está en forma consecutiva.

Ejemplo: Recibe: “ATTCAAAAATCAGGG”, retorna: “A1T2C1A5T1C1A1G3” Recibe: “AAAAAAAAAAAA”, retorna: “A12”.

5. duplicar(secuencia): retorna la secuencia recibida duplicando cada base.

Ejemplo: Recibe: “ATAGTG”, retorna: “AATTAAGGTTGG”.

6. segmentos(secuencia): retorna la cantidad de segmentos en la secuencia recibida. Un segmento se define como una secuencia de una o más bases “G”, “T” y, o “C”, delimitada por “A”.

Ejemplo: Recibe: “AATAGCACTTAC”, retorna: 3. Recibe: “AATAGCACTTACA”, retorna: 4. Recibe: “AAAAA”, retorna: 0.

7. expandir(datos): recibe un string de datos formado por bases y cantidades (se asume válido, las cantidades van de 1 a 9) y retorna la secuencia correspondiente.

Ejemplo: Recibe “A1T2C1A5T1C1A1G3”, retorna: “ATTCAAAAATCAGGG”

8. primeraBaseUnica(secuencia): retorna cuál es la posición de la primera base que está una única vez en la secuencia. Si no hay ninguna, retorna -1.

Ejemplo: Recibe “GAGTAAA”, retorna 3. Recibe: “GATAAGACTTC”, retorna -1. Recibe: “AGC” retorna 0.

9. periodica(secuencia): recibe una secuencia y retorna verdadero si es periódica, esto es, si se puede rearmar tomando un subgrupo de una o más bases sucesivas de la secuencia y replicándolos para formar la secuencia recibida, concatenando el subgrupo las veces necesarias.
Ejemplo: Recibe: “AGAG”, retorna true. Recibe: “AGA”, retorna false. Recibe: “GATGATGATGAT”, retorna true.

Código de solución

Ya mostré anteriormente lo solicitado, ahora la solución. Por cierto, ya he explicado por separado varios ejercicios que aparecen aquí, dejo los enlaces en el lugar donde corresponde.

Para el ejercicio 1 simplemente remplazamos una letra por otra. En el segundo comprobamos si empieza y termina con una subcadena, para el tercero contamos la frecuencia de letras que hay en una frase.

Siguiendo con el ejercicio 4 lo que se hace es comprimir o resumir una cadena, en el 5 duplicamos cada letra.

Luego en el 7 tenemos que expandir la cadena según el número que aparece a su lado, en el 8 comprobamos si la base aparece solo una vez y en el 9 comprobamos si la string es periódica.

# https://parzibyte.me/blog

def transformar_ADN_ARN(secuencia):
    arn = ""
    for base in secuencia:
        if base == "T":
            arn += "U"
        else:
            arn += base
    return arn


def tieneStartStop(secuencia):
    # Si no tiene el inicio, el final y algo (3 + 3 + algo) entonces no
    if len(secuencia) < 7:
        return False
    inicio = secuencia[:3]
    fin = secuencia[-3:]
    if inicio != "ATG":
        return False
    if fin != "TGA":
        return False
    parte_central = secuencia[3:-3]
    longitud_parte_central = len(parte_central)
    if longitud_parte_central % 3 != 0:
        return False

    if "ATG" in parte_central:
        return False
    if "TGA" in parte_central:
        return False
    # Si pasó todas las validaciones de arriba, entonces es válido
    return True


def mostrar(secuencia):
    longitud = len(secuencia)
    cantidad_a = 0
    cantidad_c = 0
    cantidad_t = 0
    cantidad_g = 0
    for base in secuencia:
        if base == "A":
            cantidad_a += 1
        elif base == "C":
            cantidad_c += 1
        elif base == "T":
            cantidad_t += 1
        elif base == "G":
            cantidad_g += 1

    porcentaje_a = (cantidad_a * 100) / longitud
    porcentaje_c = (cantidad_c * 100) / longitud
    porcentaje_t = (cantidad_t * 100) / longitud
    porcentaje_g = (cantidad_g * 100) / longitud
    salida = ""
    salida += "A " + ("*" * cantidad_a) + " " + str(porcentaje_a) + "% "
    salida += "C " + ("*" * cantidad_c) + " " + str(porcentaje_c) + "% "
    salida += "T " + ("*" * cantidad_t) + " " + str(porcentaje_t) + "% "
    salida += "G " + ("*" * cantidad_g) + " " + str(porcentaje_g) + "% "
    return salida


def resumir(secuencia):
    ultima_base = secuencia[0]
    salida = ""
    conteo = 0
    indice = 0
    for base in secuencia:
        if base == ultima_base:
            conteo += 1
        else:
            if conteo > 0:
                salida += ultima_base + str(conteo)
            conteo = 1
            ultima_base = base

        # Caso especial cuando llegamos al final
        if indice + 1 >= len(secuencia):
            salida += ultima_base + str(conteo)
        indice += 1
    return salida


def duplicar(secuencia):
    salida = ""
    for base in secuencia:
        salida += base*2
    return salida


def segmentos(secuencia):
    print(secuencia)
    conteo = 0
    inicio_de_segmento_encontrado = False
    for base in secuencia:
        if base == "A":
            if inicio_de_segmento_encontrado:
                conteo += 1
                inicio_de_segmento_encontrado = False
        else:
            inicio_de_segmento_encontrado = True
    return conteo


def expandir(datos):
    salida = ""
    # Hacer un ciclo "de 2 en 2", es decir, vamos en 0, 2, 4, 6, etcétera
    for i in range(0, len(datos), 2):
        # Extraer la base y cantidad
        par = datos[i:i+2]
        base = par[0]
        cantidad = int(par[1])
        # Expandimos la base multiplicando la cadena
        base_expandida = base * cantidad
        # La agregamos al resultado final
        salida += base_expandida
    return salida


def primeraBaseUnica(secuencia):
    indice = 0
    for base in secuencia:
        # Si la primera ocurrencia de izquierda a derecha (index) es la misma que de derecha a izquierda, entonces
        # esta base solo aparece una vez en la secuencia
        if secuencia.index(base) == secuencia.rindex(base):
            return indice
        indice += 1
    return -1


"""
Realizamos combinaciones de todas las subcadenas. Por ejemplo para AGAG serían las siguientes combinaciones:
A
AG
AGA
AGAG

En cada combinación que hacemos, vemos si al multiplicarla N veces se daría con la cadena completa. N es
las veces que esta subcadena cabe en toda la secuencia, redondeada al entero anterior más próximo. 
Entonces tomando en cuenta cada combinación:
A, al multiplicarla 4 veces da AAAA, no nos da la cadena AGAG entonces lo descartamos
AG, al multiplicarla 2 veces da AGAG, SÍ nos da la cadena AGAG entonces regresamos True y ya no hacemos las siguientes

Otro ejemplo, para AGA:
Para A, multiplicamos por 3. Nos da AAA, no es AGA entonces descartamos
Para AG, multiplicamos por 1, nos da AG, no es AGA entonces descartamos
Para AGA, multiplicamos por 1 y SÍ nos da AGA pero NO lo tomamos en cuneta porque la combinación mide igual que la cadena completa
Llegamos al final de las comprobaciones y regresamos False
"""


def periodica(secuencia):
    longitud_secuencia = len(secuencia)
    for i in range(longitud_secuencia):
        combinacion = secuencia[:i+1]
        longitud_combinacion = len(combinacion)
        cantidad_de_veces_que_cabe = longitud_secuencia // longitud_combinacion
        # Ver si esta subcadena, al multiplicarla por las veces que cabe, es igual a la cadena completa
        # Nota: también comprobamos si la subcadena no es exactamente igual a la cadena original
        multiplicada = combinacion*cantidad_de_veces_que_cabe
        if longitud_combinacion != longitud_secuencia and multiplicada == secuencia:
            return True
    return False


def solicitar_y_validar_secuencia():
    while True:
        secuencia = input("Ingrese la secuencia: ")
        if len(secuencia) < 1:
            print("La longitud de la secuencia debe ser mayor o igual a 1")
            continue
        for base in secuencia:
            correcto = True
            if base.upper() not in "ACTG":
                correcto = False
        if not correcto:
            print("La secuencia solo puede estar conformada por A, C, T o G")
            continue
        # Si ninguno de los "continue" de arriba se cumplió, entonces estamos bien
        # La regresamos en mayúscula porque todas las funciones suponen que estará en mayúscula
        return secuencia.upper()


def menu(secuencia_fija, secuencia):
    while True:
        opcion = input("0. Salir del programa\n1. Transformar\n2. Comprobar si tiene start y stop\n3. Mostrar\n4. Resumir\n5. Duplicar\n6. Segmentos\n7. Expandir\n8. Primera base única\n9. Periódica\nElija: ")
        if opcion == "0":
            return
        # Comprobamos si es necesario solicitar la secuencia
        if not secuencia_fija and opcion != "7":  # opción 7 no necesita secuencia
            secuencia = solicitar_y_validar_secuencia()
        if opcion == "1":
            print(transformar_ADN_ARN(secuencia))
        elif opcion == "2":
            print(tieneStartStop(secuencia))
        elif opcion == "3":
            print(mostrar(secuencia))
        elif opcion == "4":
            print(resumir(secuencia))
        elif opcion == "5":
            print(duplicar(secuencia))
        elif opcion == "6":
            print(segmentos(secuencia))
        elif opcion == "7":
            datos = input("Ingrese los datos para expandir: ")
            print(expandir(datos))
        elif opcion == "8":
            print(primeraBaseUnica(secuencia))
        elif opcion == "9":
            print(periodica(secuencia))
        else:
            print("Opción inválida")


def main():
    respuesta_secuencia_fija = input(
        "¿Desea trabajar con una secuencia fija? [s/n]: ")
    secuencia = ""
    secuencia_fija = False
    if respuesta_secuencia_fija.lower() == "s":
        secuencia = solicitar_y_validar_secuencia()
        secuencia_fija = True
    menu(secuencia_fija, secuencia)


main()

También puedes ver que, cumpliendo con los requisitos del ejercicio, se solicita la secuencia de ADN al inicio en caso de que el usuario quiera trabajar con ella en todos los puntos, y si no, se le solicita en cada punto.

El menú también está implementado. Yo ejecuté una prueba rápida y aparece lo siguiente:

Python - Ejercicios resueltos con secuencias de ADN y cadenas
Python – Ejercicios resueltos con secuencias de ADN y cadenas

Para terminar te dejo con más tutoriales y ejercicios resueltos de Python en mi blog.

Estoy aquí para ayudarte 🤝💻


Estoy aquí para ayudarte en todo lo que necesites. Si requieres alguna modificación en lo presentado en este post, deseas asistencia con tu tarea, proyecto o precisas desarrollar un software a medida, no dudes en contactarme. Estoy comprometido a brindarte el apoyo necesario para que logres tus objetivos. Mi correo es parzibyte(arroba)gmail.com, estoy como@parzibyte en Telegram o en mi página de contacto

No te pierdas ninguno de mis posts 🚀🔔

Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *