x = 20 
y = 5
print(x+y) 

"""
Explanation: Fundamentos de Python 3 en Jupyter

<br>
El lenguaje de programación Python: Funciones
End of explanation
"""


def add_numbers(x, y):
    return x + y

add_numbers(1, 2)

"""
Explanation: <br>
add_numbers es una función que toma dos números y los suma.
End of explanation
"""


def add_numbers(x,y,z=None):
    if (z==None):
        return x+y
    else:
        return x+y+z

print(add_numbers(1, 2))
print(add_numbers(1, 2, 3))

"""
Explanation: <br>
add_numbers puede actualizarse agregando un tercer parámetro. Usando print se pueden imprimir múltiples opciones en una sola celda de Jupyter.
End of explanation
"""


def add_numbers(x, y, z=None, flag=False):
    if (flag):
        print('¡Flag es verdad, y es muy útil!')
    if (z==None):
        return x + y
    else:
        return x + y + z
    
print(add_numbers(1, 2, 20, flag=True))

"""
Explanation: <br>
A add_numbers también pordemos agregarle un parámetro opcional llamado flag.
End of explanation
"""


def add_numbers(x,y,z):
    return x+y+z

a = add_numbers
a(1, 2, -5)

"""
Explanation: <br>
Se puede también asignar la función add_numbers a una variable a.
End of explanation
"""


x = (1,3,5, -6)
minimum = min(x)
print(minimum)

"""
Explanation: <br>
La función min devuelve el elemento más pequeño en un iterable o el más pequeño de dos o más argumentos.
End of explanation
"""


p = pow(2,2)
print(p)

"""
Explanation: <br>
La función pow(x,y) devuelve x a la potencia de y.
End of explanation
"""


div = 5/2
print(div)
divint = 5//2
print(divint)

"""
Explanation: <br>
La función x//y devuelve la parte entera del cociente entre x y y.
End of explanation
"""


mod1 = 4%2
print(mod1)
mod2 = 5%2
print(mod2)

"""
Explanation: <br>
La función x%y devuelve el resto de la división entre x y y.
End of explanation
"""


type('Esto es una cadena de caracteres')

type(None)

type(10000)

type(100000.0)

type(add_numbers)

"""
Explanation: <br>
El lenguaje de programación Python: Tipos y Secuencias
<br>
Use type para devolver el tipo del objeto.
End of explanation
"""


x = (1, 'b', 25, 'c')
print(type(x))
y = [1, 'b', 25, 'c']
print(type(y))

"""
Explanation: <br>
Una tupla es una estructura de dato inalterable. Las tuplas son secuencias, al igual que las listas. La diferencia entre las tuplas y las listas es que las tuplas no se pueden modificar a diferencia de las listas. Las tuplas usan paréntesis, mientras que las listas usan corchetes.
End of explanation
"""


y.append(2.5)
print(y)

"""
Explanation: <br>
Veamos algunas modificaciones en la estructura de datos lista.
<br>
Usemos append para gregar un elemento a la lista.
End of explanation
"""


for elemento in y:
    print(elemento)

"""
Explanation: <br>
Este es un ejemplo de cómo se puede hacer un ciclo para recorrer los elementos de la lista.
End of explanation
"""


i=0
while( i != len(y) ):
    print(y[i])
    i = i + 1

"""
Explanation: <br>
O podemos utilizar el operador de índices:
End of explanation
"""


[1,25] + [3,'z']

"""
Explanation: <br>
Use + para concatenar listas.
End of explanation
"""


[3, 'z']*4

"""
Explanation: <br>
Use * para repetir listas.
End of explanation
"""


'z' in [3,'z', 25]

"""
Explanation: <br>
Use el operador in para chequear si algo está dentro de la lista.
End of explanation
"""


y =[2, 'c', 34, -2, 'f']
print(y[1]) #primer elemento de la lista
print(y[0:1]) #primer elemento devuelto como lista
print(y[0:2]) #dos primeros elementos devueltos como lista

x = 'Esto es una cadena de caracteres'
print(x[0]) #primer caracter
print(x[0:1]) #primer caracter, especificando último caracter
print(x[0:2]) #dos primeros caracteres

"""
Explanation: <br>
Use la notación bracket [] para picar o rebanar listas o cadenas de caracteres
End of explanation
"""


print(y[-1])
print(x[-1])

"""
Explanation: <br>
Esta instrucción devuelve el último elemento de la lista o de la cadena.
End of explanation
"""


print(y)
print(y[-4:-2])
print(x)
print(x[-4:-2])

"""
Explanation: <br>
Esta instrucción devuelve un pedazo de la lista o cadena empezando desde el cuarto elemento desde el final y deteniéndose antes del segundo elemento del final.
End of explanation
"""


print(y)
print(y[:3])
print(x)
print(x[:3])

"""
Explanation: <br>
Este es un pedazo de la lista o cadena desde el inicio y se detiene antes del tercer elemento.
End of explanation
"""


print(y)
print(y[3:])
print(x)
print(x[3:])

"""
Explanation: <br>
Y este es un pedazo de la lista o cadena empezando desde el tercer elemento y siguiendo hasta el final.
End of explanation
"""


import csv

with open('empleados_cumple.txt') as csv_file:
    csv_reader = csv.reader(csv_file, delimiter=',')
    line_count = 0
    for row in csv_reader:
        if line_count == 0:
            print(f'Los nombres de las columnas son: {", ".join(row)}')
            line_count += 1
        else:
            print(f'\t{row[0]} trabaja en el departamento de {row[1]}, y nació en el mes de {row[2]}.')
            line_count += 1
    print(f'Líneas procesadas: {line_count}.')

"""
Explanation: <br>
Leer y escribir archivos CSV
<br>
Vamos a importar un archivo txt como 
uno CSV que contiene como columnas las etiquetas:

Nombre,Departamento,Mes de Cumpleaños

Y como filas:

Adelis Nieves, Matemáticas, Junio
Miguel Astor, Redes, Septiembre
Francisco Sans, Computación Gráfica, Diciembre
Antonio Escalante, Letras, Diciembre
End of explanation
"""


import numpy as np

"""
Explanation: <br>
Lenguaje de programación Python: Python Numérico (NumPy)
End of explanation
"""


milista = [1, 25, 31, 5]
x = np.array(milista)
x

"""
Explanation: Creando arreglos
<br>
Podemos generar una lista y convertirla en un arreglo NumPy.
End of explanation
"""


y = np.array([1, 25, 31, 5])
y

"""
Explanation: <br>
O simplemente podemos pasarle una lista directamente.
End of explanation
"""


m = np.array([[1, 25, 31, 5], [10, 2, 11, 12], [5, 7, 0, 1]])
m

"""
Explanation: <br>
Podemos pasarle una lista de listas para crear un arreglo multidimensional.
End of explanation
"""


m.shape

"""
Explanation: <br>
Usa el método shape para encontrar las dimensiones del arreglo. (filas, columnas)
End of explanation
"""


n = np.arange(0, 30, 2) # empieza en 0 cuenta de 2 en 2, se detiene antes de 30
n

"""
Explanation: <br>
arange devuelve valores espaciados uniformemente dentro de un intervalo dado.
End of explanation
"""


n = n.reshape(3, 5) #cambia la forma de manera que se obtenga una matriz 3x5
n

"""
Explanation: <br>
reshape devuelve una matriz con los mismos datos con una nueva forma.
End of explanation
"""


p = np.ones([2, 3], int)
p

"""
Explanation: Combinando arreglos
End of explanation
"""


np.vstack([p, 2*p])

"""
Explanation: <br>
Use vstack para apilar matrices en secuencia verticalmente (por fila).
End of explanation
"""


np.hstack([p, 2*p])

"""
Explanation: <br>
Use hstack para apilar arreglos en secuencia horizontalmente (por columna).
End of explanation
"""


print(x)
print(y)
print(x + y) # suma elemento a elemento     [1 2 3] + [4 5 6] = [5  7  9]
print(x - y) # resta elemento a elemento  [1 2 3] - [4 5 6] = [-3 -3 -3]

print(x)
print(y)
print(x * y) # multiplicación elemento a elemento  [1 2 3] * [4 5 6] = [4  10  18]
print(x / y) # división elemento a elemento         [1 2 3] / [4 5 6] = [0.25  0.4  0.5]

print(x)
print(x**2) # potencia elemento a elemento   [1 2 3] ^2 =  [1 4 9]

"""
Explanation: Operaciones
Use +, -, *, / and ** para realizar operaciones de suma , resta, multiplicación, división y potencia elemento a elemento.
End of explanation
"""


print(x)
print(y)
x.dot(y) #producto escalar 

print(y)
z = np.array([y, y**2])
print(z)
print(len(z)) #número de filas del arreglo

"""
Explanation: Producto punto o escalar:  
$ \begin{bmatrix}x_1 \ x_2 \ x_3\end{bmatrix}
\cdot
\begin{bmatrix}y_1 \ y_2 \ y_3\end{bmatrix}
= x_1 y_1 + x_2 y_2 + x_3 y_3$
End of explanation
"""


zt = np.transpose(z, axes=None)
zt

"""
Explanation: <br>
Vamos a mirar la transposición de matrices. La transposición permuta las dimensiones de la matriz.
End of explanation
"""


zt.shape

"""
Explanation: <br>
Las dimensiones del arreglo zt son (4,2) después de la transposición.
End of explanation
"""


print(zt)
zt.T

"""
Explanation: <br>
Se puede usar también .T para obtener la transpuesta de un arreglo.
End of explanation
"""


s = np.arange(13)**2
s

"""
Explanation: Indexando/Rebanando
End of explanation
"""


s[0], s[4], s[-1]

"""
Explanation: <br>
Use la notación de bracket [] para obtener valores en el índice indicado. Recuerde que la indexación comienza en 0.
End of explanation
"""


s[1:5]

"""
Explanation: <br>
Use : para indicar un rango. array[empieza:termina]
Dejando empieza or termina vacío quedará predeterminado al principio / final de la matriz.
End of explanation
"""


s[-4:]

"""
Explanation: <br>
Use contadores negativos desde el final.
End of explanation
"""


s[-5::-2]

"""
Explanation: <br>
Se puede usar un segundo : para indicar el tamaño del paso. array [empieza: termina: paso]
Aquí estamos comenzando el quinto elemento desde el final, y contando hacia atrás cada 2 hasta que se alcanza el comienzo de la matriz.
End of explanation
"""


