Artículo

Esta es la continuación del articulo Primeros pasos en Python.

Yo sé que somos muchos los que estamos muy interesados en programar. Pero es posible que también hagamos parte de aquellos a los que nos da una pereza inconcebible tener que ver una tonelada de teoría antes de ir a la practica. Y en ninguna manera condono la apatía a la teoría, pero a veces toca ensuciarse las manos un poco antes de descubrir un nuevo hobby.

Esta serie de artículos van un poco en el espíritu del libro Inmersión en Python3 (Originalmente Dive Into Python 3 por Mark Pilgrim). Este libro entra en materia sin mucha explicación y espera que los lectores tomen lo que ven como base e investiguen lo necesario para entender. Entonces esta serie de artículos pueden contener cosas que desconozcas, pero espero que estés dispuesto(a/x) a investigar.

El Problema a Resolver

Bien , empecemos declarando el problema a resolver; lo podemos encontrar en este link. En español quedaría así:

Objetivo

Crea un programa que imprime cada lineal de la canción "99 Bottles of Beer on the Wall". Esto debería ser un programa sencillo, entonces, para hacerlo un poco mas difícil, aquí siguen algunas reglas a seguir:

Reglas
  1. Si vas a usar una lista de todos los números, no los escribas manualmente todos. En cambio, usa una función estándar de Python.
  2. Aparte de la frase "take one down", no tienes permitido escribir ningun numero/nombre de numero directo en la letra.
  3. Recuerda, cuando llegues a 1 botella, la palabra "bottles" se vuelve singular.
  4. Pon una linea en blanco entre cada verso de la canción.

Analisis y Programación

Vamos entonces a ver donde encontramos la letra completa de la canción y la analizamos. Una pequeña búsqueda en Google me ha provisto del siguiente enlace donde encontrar la letra de la canción.

En definitiva no la voy a escribir entera aquí porque no tiene sentido desperdiciar ese espacio cuando puedes abrirla en otra pestaña ; ); pero si vamos a escribir 3 estrofas:

One-hundred bottles of beer on the wall, 
One-hundred bottles of beer!
Take one down,
Pass it around,
Ninety-nine bottles of beer on the wall!

Ninety-nine bottles of beer on the wall,
Ninety-nine bottles of beer!
Take one down,
Pass it around,
Ninety-eight bottles of beer on the wall!
One bottle of beer on the wall,
One bottle of beer!
Take it down,
Pass it around,
No more bottles of beer on the wall!

Primero: Intentar resolver el problema principal

Veamos que se repite y reescribamos la canción, lo que se repite lo pongo entre corchetes "[]" y lo que varía en "{}":

{{Numero de botellas}}[ bottles of beer on the wall,]
{{Numero de botellas}}[ bottles of beer!]
[Take one down,
Pass it around,]
{{Numero de botellas-1}}[ bottles of beer on the wall!]

Y todo estaría perfecto si no fuera porque la ultima estrofa es diferente, por lo tanto...

Segundo: Las miles de excepciones

Una excepción nos dañaría el caminado, denoto la condicional con dobles corchetes "{{}}":

{{Cuando quede una botella}}
    {{1}}[bottle of beer on the wall,]
    {{1}}[bottle of beer!]
    [Take it down,
    Pass it around,
    No more bottles of beer on the wall!]

Con esto tenemos la estructura de lo que queremos lograr, ahora necesitamos conocer que herramientas tenemos...

Tercero: Herramientas disponibles

Las herramientas serían varias, lo que creo necesitar es lo siguiente:

  • La herramienta for nos ayuda a recorrer elementos iterables, pero no necesariamente esos son números.
  • Podemos generar un iterable de numeros usando la herramienta range.
  • También necesitamos algún tipo de condicional y la herramienta if será la opción escogida.

Estas herramientas las encontramos en la documentación oficial de python; están en la sección de herramientas para control de flujo.

Procedamos entonces a construir con estas herramientas el esqueleto de nuestro programa. Ten presente que para esto creo un archivo llamado tercero.py en una carpeta llamada 01_primer_paso.

for x in range(100,-1,-1):
    if x==1:
        print('Lo que va cuando sea una botella '+str(x))
    else:
        print('Lo que va cuando son varias botellas '+str(x))

Podrías buscar por tu cuenta que función cumple str().

Veamos que produce esto:

[email protected]_pc:~/pybaq_caminemos_juntos/01_primer_paso$ python3 tercero.py
Lo que va cuando son varias botellas 100
Lo que va cuando son varias botellas 99
...
Lo que va cuando son varias botellas 2
Lo que va cuando sea una botella 1
Lo que va cuando son varias botellas 0

Ahora necesitamos resolver lo del texto, básteme decir que existe algo en python llamado f-string, lee al respecto aquí y aqui. Creo 2 f-trings; una por cada condición. En una primera variable bottles_sing (botellas cantan) asigno una f-string multi-linea para los casos plurales, luego a una segunda variable bottle_sings (botella canta) otra f-tring para la condición en singular de una botella:

for x in range(100,0,-1):
    bottle_num=x
    if x==1:
        bottle_sings=(
        f"{bottle_num} bottle of beer on the wall,\n"
        f"{bottle_num} bottle of beer! \n"
        f"Take it down,\nPass it around,\nNo more bottles of beer on the wall!\n"
        )
        print(bottle_sings)
    else:
        bottles_sing=(
        f"{bottle_num} bottles of beer on the wall,\n"
        f"{bottle_num} bottles of beer!\n"
        f"Take it down,\nPass it around,\nNo more bottles of beer on the wall!\n"
        f"{bottle_num-1} bottles of beer on the wall!\n"
        )
        print(bottles_sing)

El resultado de la ejecución es el siguiente:

[email protected]_pc:~/pybaq_caminemos_juntos/01_primer_paso$ python3 tercero_b.py
100 bottles of beer on the wall,
100 bottles of beer!
Take it down,
Pass it around,
No more bottles of beer on the wall!
99 bottles of beer on the wall!

99 bottles of beer on the wall,
99 bottles of beer!
Take it down,
Pass it around,
No more bottles of beer on the wall!
98 bottles of beer on the wall!

...

1 bottle of beer on the wall,
1 bottle of beer!
Take it down,
Pass it around,
No more bottles of beer on the wall!

El articulo oficialmente debería terminar aquí. Pero algunos podrían no quedar satisfechos, por lo que voy a hablar de algo un poco mas complicado, puedes investigar por tu cuenta acerca de PyPI y la herramienta pip; pero no te enredes la vida sin necesidad, veremos mas de eso después.

Bonus: Exageremos un poco

En Python tenemos un gestor de librerias llamada pip, con el podemos instalar librerías adicionales de un repositorio central llamado PyPI. Allí encontré algunas librerías que podrían ser utiles para imprimir texto en vez de numeros.

Tras escoger num2words e instalarlo en mi PC (usando el comando pip install num2words), puedo modificar el código de la siguiente manera:

from num2words import num2words

for x in range(100,0,-1):
    bottle_num= num2words(x).capitalize()
    bottle_num_minusone= num2words(x-1).capitalize()
    if x==1:
        bottle_sings=(
        f"{bottle_num} bottle of beer on the wall,\n"
        f"{bottle_num} bottle of beer! \n"
        f"Take it down,\nPass it around,\nNo more bottles of beer on the wall!\n"
        )
        print(bottle_sings)
    else:
        bottles_sing=(
        f"{bottle_num} bottles of beer on the wall,\n"
        f"{bottle_num} bottles of beer!\n"
        f"Take it down,\nPass it around,\nNo more bottles of beer on the wall!\n"
        f"{bottle_num_minusone} bottles of beer on the wall!\n"
        )
        print(bottles_sing)

El resultado habla por sí mismo:

[email protected]_pc:~/pybaq_caminemos_juntos/01_primer_paso$ python3 bonus.py
...
Three bottles of beer on the wall,
Three bottles of beer!
Take it down,
Pass it around,
No more bottles of beer on the wall!
Two bottles of beer on the wall!

Two bottles of beer on the wall,
Two bottles of beer!
Take it down,
Pass it around,
No more bottles of beer on the wall!
One bottles of beer on the wall!

One bottle of beer on the wall,
One bottle of beer!
Take it down,
Pass it around,
No more bottles of beer on the wall!

¿He comprendido algo maestro?

El que quiera hacer la voluntad de Dios, conocerá si la doctrina es de Dios, o si yo hablo por mi propia cuenta

Juan 7:17

Fuera de lo pretensioso de tratar de compararme con Jesucristo (aún si lo consideras una fábula), la idea es que solo tratando de replicar lo que aprendemos podemos interiorizar el tema aprendido. Entonces, evalúa tu conocimiento o entendimiento con las siguientes tareas:

  • Traduce la canción a español. Si no hablas inglés un traductor se encarga de esa parte y tu de editar código.
  • Automatiza la canción "Un elefante se balanceaba" hasta 100 elefantes.
  • Crea el "me quiere, no me quiere" de una flor de 18 pétalos.

También puedes consultar algo de teoría:

  • ¿Que son las estructuras de control en un lenguaje de programación?
  • ¿Que es un iterable en Python?
  • ¿Que otros tipos de cadenas de texto existen y como se usan?

¿Tienes preguntas? Escríbeme en Twitter. Podemos conectarnos y resolver dudas juntos.