# necesito calcular el cuadrado de un número
# defino una variable asignándole el valor 6
n = 6

# calculo el cuadrado y lo imprimo por pantalla
cuadrado = n**2
print(cuadrado)

# ahora me piden que calcule otro cuadrado, en este caso de 8
# repito el proceso
n = 8
cuadrado = n**2
print(cuadrado)

"""
Explanation: Funciones
Una función es una sección de código reutilizable, escrita para realizar una tarea específica en un programa. 
¿Por qué son útiles las funciones? Fíjate en los siguientes ejemplos.
End of explanation
"""


# creamos una función llamada cuadrado que toma como entrada
# un número cualquiera y devuelve el cuadrado de dicho número

def cuadrado(numero):
    """devuelve el cuadrado del número especificado como entrada"""
    micuadrado = numero**2
    return micuadrado

# las variables definidas dentro de funciones limitan su alcance al interior de la funcion
# si tratas de utilizarlas fuera, es como si nunca las hubieras creado
# esta celda, da error
print(micuadrado)

"""
Explanation: Imagina que por tercera vez, me piden que calcule un cuadrado. ¿Repito el proceso de manera indefinida? 
El ejemplo es un poco extremo, pero sirve para ilustrar que, a veces, nuestros programas repiten siempre el mismo proceso (en este caso, un cálculo) variando los datos con los que trabajamos. En este caso, es mucho más eficaz reutilizar el código y adaptarlo ligeramente para generalizar el cálculo de cuadrados a cualquier número.
¿Me sigues? ¿Sí? Pues vamos a ver cómo hacerlo definiendo una función.
La sintaxis de una función forma un bloque de código de la siguiente manera:
def FUNCION(ENTRADA):
    """comentario explicando qué hace esta función"""
    SALIDA = INSTRUCCIONES
    return SALIDA

Las funciones se definen usando la instrucción def y están compuestas de tres partes:

El encabezado, que incluye la instrucción def, el nombre de la función, cualquier argumento que contenga la función especificado entre paréntesis (), y el signo de dos puntos :.
Una cadena de documentación con tres pares de comillas, que explica de forma breve qué hace la función.
El cuerpo, que es el bloque de código que describe los procedimientos que la función lleva a cabo. El cuerpo es un bloque de código y por eso aparece indentado (de igual forma que las sentencias if, elif, y else)
Una función siempre devuelve algo: una estructura de datos, un mensaje, etc. Por lo tanto, la última línea de cualquier función es una instrucción return.

Piensa en la función como una especie de artefacto o caja negra que toma una entrada, la manipula/procesa/convierte/modifica y devuelve un resultado.
End of explanation
"""


print(cuadrado(6))

print(cuadrado(8+1))

print(cuadrado(3) + 1)

otroNumero = cuadrado(235.9)

print(otroNumero)

# en esta celda estoy ejecutando una función indicando un argumento de tipo cadena
# y falla porque la función reliza operaciones matemáticas que solo funcionan con números
print(cuadrado("a"))

"""
Explanation: Una vez definida una función, podemos llamarla tantas veces sea necesario y ejecutarla en cualquier sitio de distintas maneras. Fíjate en los ejemplos:
End of explanation
"""


cuadrado??

"""
Explanation: Fíjate por qué es importante añadir una cadena de texto entre comillas triples en nuestras funciones: sirve como documentación (docstring) de ayuda cuando utilizamos la función help() o accedemos a la ayuda de iPython.
End of explanation
"""


def cubo(numero):
    """devuelve el cubo del número especificado como entrada"""
    return numero**3

print(cubo(2))

# un millar es 10^3
millar = cubo(10)
print(millar)

"""
Explanation: En realidad, ya conoces unas cuantas funciones que existen de manera predefinida en Python. ¿Recuerdas las funciones len() y type(), por ejemplo, para calcular la longitud y el tipo de las estructuras de datos? Ahora lo único que estamos haciendo es definiendo nuestras propias funciones.
Siguiendo con las operaciones, imagínate ahora que nos piden calcular cubos de distintos números, podríamos definir una función llamada cubo:
End of explanation
"""


def potencia(base, exponente):
    """calcula potencias"""
    return base**exponente

# calcula 10^2
print(potencia(10, 2))

# calcula 32^5
print(potencia(32, 5))

# un billón es un 10 seguido de 12 ceros
billon = potencia(10, 12)
print(billon)

"""
Explanation: Podemos generalizar más y definir una función para calcular potencias, de manera que tomemos como entrada dos números, la base y el exponente.
End of explanation
"""


def saludo():
    """Imprime un saludo por pantalla"""
    print("¡Hola, amigo!")

"""
Explanation: Antes hemos mencionado que una función debía de devolver simpre algún valor, y por eso todas las definiciones de funciones terminan con una instrucción return. Bien, esto no era del todo cierto. Fíjate en este ejemplo.
End of explanation
"""


for i in range(3):
    saludo()
    
# fíjate cómo el valor de i se actualiza en cada iteración
for i in range(10):
    print("Voy por el número", i)

"""
Explanation: En esta celda utilizo la función range que no habíamos visto antes para indicar el número exacto de veces que quiero que se ejecute un bucle for.
Fíjate en cómo la función range, cuando se ejecuta con un único argumento N, devuelve una lista con N números sobre la que podemos iterar. Bueno, en realidad, esto no es correcto. La realidad es que devuelve una estructura de datos especial llamada iterador, con los números enteros entre el 0 y N-1). Pero para nuestros intereses, es mejor la primera explicación.
End of explanation
"""


# range devuelve los números entre el 10 al 19
for i in range(10, 20):
    print(i)
    
print("-------------------")

# range devuelve los números del 10 al 19, avanzando de 3 en 3
for i in range(10, 20, 3):
    print(i)

range??

"""
Explanation: range se puede ejecutar también con dos y tres argumenos numéricos. Cuando especificamos dos argumentos, podemos definir el primer y el último elemento de la lista resultante. Cuando especificamos tres, el último indica el salto entre cada par de elemenos. Fíjate en estos ejemplos.
End of explanation
"""


def pluralize(word):
    """Convierte a plural cualquier palabra singular en inglés"""
    return word + "s"

"""
Explanation: Obviamente, podemos definir funciones que hagan otras cosas diferentes a cálculo de potencias. Pensemos en un ejemplo de tratamiento de texto que nos puede resultar más útil.
End of explanation
"""


print(pluralize("cat"))
print(pluralize("question"))

print(pluralize("berry"))
print(pluralize("business"))
print(pluralize("box"))
print(pluralize("flush"))
print(pluralize("coach"))

# plurales irregulares
print(pluralize("foot"))
print(pluralize("woman"))
print(pluralize("child"))

def terminaEnVocal(palabra):
    """comprueba si una palabra termina en vocal"""
    vocales = "aeiou"
    if palabra[-1] in vocales:
        return True
    else:
        return False
    
    
print(terminaEnVocal("cava"))
print(terminaEnVocal("jamón"))    

def convierteAMayusculaLaUltimaLetra(palabra):
    """devuelve la palabra transformando la última letra a mayúscula"""
    return palabra[:-1] + palabra[-1].upper() 
    
print(convierteAMayusculaLaUltimaLetra("cava"))
print(convierteAMayusculaLaUltimaLetra("jamón"))    

print("berry"[:-1] + "ies")

def pluralize(word):    
    """Convierte a plural cualquier palabra singular en inglés"""
    if word.endswith("ss") or word.endswith("x"):
        return word + "es"
    else:
        return word + "s"

"""
Explanation: ¿Te atreves a modificar el código para:

que funcionen correctamente las palabras acabadas en -s?
manejar plurales irregulares?
End of explanation
"""


