diff --git a/02-numpy/02.1-Intro-to-Numpy.es.ipynb b/02-numpy/02.1-Intro-to-Numpy.es.ipynb new file mode 100644 index 0000000..3b6bd7f --- /dev/null +++ b/02-numpy/02.1-Intro-to-Numpy.es.ipynb @@ -0,0 +1,811 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "bdfbcacc", + "metadata": { + "id": "bdfbcacc" + }, + "source": [ + "![Logo de NumPy](https://github.com/4GeeksAcademy/machine-learning-prework/blob/main/02-numpy/assets/numpy_logo.png?raw=true)\n", + "\n", + "## Introducción a NumPy\n", + "\n", + "`NumPy` es un juego de palabras que significa **Python numérico** (*Numerical Python*). Es una librería de código abierto que se utiliza para llevar a cabo tareas matemáticas con altísima eficiencia. Además, introduce estructuras de datos como los arrays multidimensionales, que se pueden operar entre ellos a alto nivel, sin meterse mucho en el detalle.\n", + "\n", + "En concreto, las claves de esta librería son:\n", + "\n", + "- **Array multidimensionales**: Esta librería proporciona un objeto llamado `ndarray`, que permite almacenar y manipular grandes conjuntos de datos de forma eficiente. Los arrays pueden tener cualquier número de dimensiones.\n", + "- **Operaciones Vectorizadas**: NumPy permite realizar operaciones matemáticas en arrays completos sin la necesidad de bucles explícitos en el código, lo que lo hace muy rápido y eficiente.\n", + "- **Funciones matemáticas**: NumPy proporciona una amplia gama de funciones matemáticas para trabajar con arrays, incluyendo funciones trigonométricas, estadísticas, álgebra lineal, entre otras.\n", + "- **Eficiencia**: Es mucho más rápido que la misma funcionalidad implementada directamente sobre Python nativo. Además, es muy flexible en términos de acceso y manipulación de elementos individuales o subconjuntos de arrays.\n", + "\n", + "NumPy es una biblioteca fundamental para el Machine Learning y la ciencia de los datos en Python. Proporciona una amplia gama de herramientas y funciones para trabajar eficientemente con datos numéricos en forma de arrays y matrices." + ] + }, + { + "cell_type": "markdown", + "id": "dc410026", + "metadata": { + "id": "dc410026" + }, + "source": [ + "### Arrays\n", + "\n", + "Un **array** de NumPy es una estructura de datos que permite almacenar una colección de elementos, generalmente números, en una o más dimensiones.\n", + "\n", + "#### Array unidimensional\n", + "\n", + "Un array unidimensional (1D) de NumPy es una estructura de datos que contiene una secuencia de elementos en una única dimensión. Es similar a una lista en Python, pero con las ventajas de rendimiento y funcionalidad que ofrece NumPy.\n", + "\n", + "![Array de una dimensión](https://github.com/4GeeksAcademy/machine-learning-prework/blob/main/02-numpy/assets/1D.png?raw=true \"1D\")\n", + "\n", + "Un array 1D puede ser creado usando la función `array` de la librería con una lista de elementos como argumento. Por ejemplo:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d8a0686b", + "metadata": { + "id": "d8a0686b", + "outputId": "77d96640-1fc6-4709-9573-3c73e01a7b59" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([1, 2, 3, 4, 5])" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import numpy as np\n", + "\n", + "array = np.array([1, 2, 3, 4, 5])\n", + "array" + ] + }, + { + "cell_type": "markdown", + "id": "e090f7a0", + "metadata": { + "id": "e090f7a0" + }, + "source": [ + "Esto creará un array 1D con los elementos 1, 2, 3, 4 y 5. Los elementos del array deben ser del mismo tipo de datos. Si los elementos son de diferentes tipos, NumPy intentará convertirlos al mismo tipo si es posible.\n", + "\n", + "En un array 1D, podemos acceder a los elementos usando **índices** (*indexes*), modificarlos y realizar operaciones matemáticas en el array completo de forma eficiente. A continuación se muestran algunas operaciones que se pueden realizar utilizando el array anterior:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a56cb1b0", + "metadata": { + "id": "a56cb1b0", + "outputId": "07f11f37-9d8b-49d2-b8ec-e8d85f1bee04" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3\n", + "[1 7 3 4 5]\n", + "[11 17 13 14 15]\n", + "70\n" + ] + } + ], + "source": [ + "# Acceder al tercer elemento\n", + "print(array[2])\n", + "\n", + "# Cambiar el valor del segundo elemento\n", + "array[1] = 7\n", + "print(array)\n", + "\n", + "# Sumar 10 a todos los elementos\n", + "array += 10\n", + "print(array)\n", + "\n", + "# Calcular la suma de los elementos\n", + "sum_all = np.sum(array)\n", + "print(sum_all)" + ] + }, + { + "cell_type": "markdown", + "id": "322771b1", + "metadata": { + "id": "322771b1" + }, + "source": [ + "#### Array N-dimensional\n", + "\n", + "Un array multidimensional o n-dimensional en NumPy es una estructura de datos que organiza elementos en múltiples dimensiones (ejes). Estos arrays permiten representar estructuras de datos más complejas, como matrices (array 2D, 2 ejes), tensores (array 3D, 3 ejes) y estructuras de mayor dimensión.\n", + "\n", + "![Arrays de diferentes dimensiones](https://github.com/4GeeksAcademy/machine-learning-prework/blob/main/02-numpy/assets/3D.png?raw=true \"3D\")\n", + "\n", + "Un array N-dimensional puede ser creado también usando la función `array` de la librería. Por ejemplo, si queremos crear un array 2D:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2033ba3c", + "metadata": { + "id": "2033ba3c", + "outputId": "19968bc0-0de3-4433-fa27-55b789a84b84" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1, 2, 3],\n", + " [4, 5, 6],\n", + " [7, 8, 9]])" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "array_2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])\n", + "array_2d" + ] + }, + { + "cell_type": "markdown", + "id": "d3dac6c2", + "metadata": { + "id": "d3dac6c2" + }, + "source": [ + "Si ahora quisiéramos crear un array 3D, tendríamos que pensar en él como una lista de matrices:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bc914841", + "metadata": { + "id": "bc914841", + "outputId": "1fdb6e60-65f6-4aef-89c4-e76e13bf0d79" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[[1, 2],\n", + " [3, 4]],\n", + "\n", + " [[5, 6],\n", + " [7, 8]]])" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "array_3d = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])\n", + "array_3d" + ] + }, + { + "cell_type": "markdown", + "id": "da7bcb64", + "metadata": { + "id": "da7bcb64" + }, + "source": [ + "Al igual que sucedía con los arrays 1D, los elementos en un array multidimensional son accesibles mediante índices, se pueden realizar operaciones con ellos, etcétera.\n", + "\n", + "A medida que agregamos más dimensiones, el principio básico sigue siendo el mismo: cada dimensión adicional puede considerarse como un nivel adicional de anidamiento. Sin embargo, a nivel práctico, trabajar con arrays de más de 3 o 4 dimensiones puede volverse más complejo y menos intuitivo.\n", + "\n", + "Los arrays n-dimensionales en NumPy permiten una gran flexibilidad y potencia para representar y manipular datos en formas más complejas, especialmente útiles en campos como la ciencia de los datos, procesamiento de imágenes y aprendizaje profundo." + ] + }, + { + "cell_type": "markdown", + "id": "d699ac98", + "metadata": { + "id": "d699ac98" + }, + "source": [ + "### Funciones\n", + "\n", + "NumPy proporciona una gran cantidad de funciones predefinidas y que se pueden aplicar directamente sobre las estructuras de datos vistas anteriormente o las propias de Python (listas, matrices, etcétera). Algunas de las más utilizadas en el análisis de datos son:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e7680306", + "metadata": { + "id": "e7680306", + "outputId": "3a6913e7-c089-4773-bbdf-dc32c1ea52aa" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Suma: [ 6 7 8 9 10]\n", + "Producto: [ 3 6 9 12 15]\n", + "Logaritmo natural: [0. 0.69314718 1.09861229 1.38629436 1.60943791]\n", + "Exponencial: [ 2.71828183 7.3890561 20.08553692 54.59815003 148.4131591 ]\n", + "Media: 3.0\n", + "Mediana: 3.0\n", + "Desviación estándar: 1.4142135623730951\n", + "Varianza: 2.0\n", + "Máximo valor: 5\n", + "Índice del máximo valor: 4\n", + "Mínimo valor: 1\n", + "Índice del mínimo valor: 0\n", + "Suma de todos los elementos: 15\n", + "Redondeo: [1. 2. 4. 5.]\n", + "Entero menor (floor): [1. 2. 3. 4.]\n", + "Entero mayor (ceil): [2. 3. 4. 5.]\n" + ] + } + ], + "source": [ + "import numpy as np\n", + "\n", + "# Crear un array para el ejemplo\n", + "arr = np.array([1, 2, 3, 4, 5])\n", + "\n", + "# Operaciones Aritméticas\n", + "print(\"Suma:\", np.add(arr, 5))\n", + "print(\"Producto:\", np.multiply(arr, 3))\n", + "\n", + "# Logarítmicas y Exponenciales\n", + "print(\"Logaritmo natural:\", np.log(arr))\n", + "print(\"Exponencial:\", np.exp(arr))\n", + "\n", + "# Funciones Estadísticas\n", + "print(\"Media:\", np.mean(arr))\n", + "print(\"Mediana:\", np.median(arr))\n", + "print(\"Desviación estándar:\", np.std(arr))\n", + "print(\"Varianza:\", np.var(arr))\n", + "print(\"Máximo valor:\", np.max(arr))\n", + "print(\"Índice del máximo valor:\", np.argmax(arr))\n", + "print(\"Mínimo valor:\", np.min(arr))\n", + "print(\"Índice del mínimo valor:\", np.argmin(arr))\n", + "print(\"Suma de todos los elementos:\", np.sum(arr))\n", + "\n", + "# Funciones de Redondeo\n", + "arr_decimal = np.array([1.23, 2.47, 3.56, 4.89])\n", + "print(\"Redondeo:\", np.around(arr_decimal))\n", + "print(\"Entero menor (floor):\", np.floor(arr_decimal))\n", + "print(\"Entero mayor (ceil):\", np.ceil(arr_decimal))" + ] + }, + { + "cell_type": "markdown", + "id": "51b5cda3", + "metadata": { + "id": "51b5cda3" + }, + "source": [ + "## Ejercicios: Haz clic en \"open in colab\" para realizarlos\n", + "\n", + "> Solución: https://github.com/4GeeksAcademy/machine-learning-prework/blob/main/02-numpy/02.1-Intro-to-Numpy_solutions.ipynb\n", + "\n", + "### Creación de arrays" + ] + }, + { + "cell_type": "markdown", + "id": "e3c20b3d", + "metadata": { + "id": "e3c20b3d" + }, + "source": [ + "#### Ejercicio 01: Crea un **vector nulo** (*null vector*) que tenga 10 elementos (★☆☆)\n", + "\n", + "Un vector nulo es un array de una dimensión compuesto por ceros (`0`).\n", + "\n", + "> NOTA: Revisa la función `np.zeros` (https://numpy.org/doc/stable/reference/generated/numpy.zeros.html)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "8a758bcf", + "metadata": { + "id": "8a758bcf", + "outputId": "dcd7d99b-e598-44a4-a37b-8cf6e231b79a", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])" + ] + }, + "metadata": {}, + "execution_count": 6 + } + ], + "source": [ + "import numpy as np\n", + "null_vector = np.zeros(10)\n", + "null_vector" + ] + }, + { + "cell_type": "markdown", + "id": "6cbe7954", + "metadata": { + "id": "6cbe7954" + }, + "source": [ + "#### Ejercicio 02: Crea un vector de unos que tenga 10 elementos (★☆☆)\n", + "\n", + "> NOTA: Revisa la función `np.ones` (https://numpy.org/doc/stable/reference/generated/numpy.ones.html)" + ] + }, + { + "cell_type": "code", + "source": [ + "import numpy as np\n", + "vector_ones=np.ones(10)\n", + "vector_ones" + ], + "metadata": { + "id": "1FGMa3pvUWdI", + "outputId": "2bfeea6c-ec07-48a1-d6af-32b99076fc72", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "id": "1FGMa3pvUWdI", + "execution_count": 2, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])" + ] + }, + "metadata": {}, + "execution_count": 2 + } + ] + }, + { + "cell_type": "markdown", + "id": "0a708990", + "metadata": { + "id": "0a708990" + }, + "source": [ + "#### Ejercicio 03: Investiga la función `linspace` de NumPy y crea un array que contenga 10 elementos (★☆☆)\n", + "\n", + "> NOTA: Revisa la función `np.linspace` (https://numpy.org/doc/stable/reference/generated/numpy.linspace.html)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "477e01f4", + "metadata": { + "id": "477e01f4", + "outputId": "c9b8c3ff-328d-4b86-a977-016294204cc3", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "array([1. , 1.44444444, 1.88888889, 2.33333333, 2.77777778,\n", + " 3.22222222, 3.66666667, 4.11111111, 4.55555556, 5. ])" + ] + }, + "metadata": {}, + "execution_count": 3 + } + ], + "source": [ + "import numpy as np\n", + "array=np.linspace(1,5,10)\n", + "array" + ] + }, + { + "cell_type": "markdown", + "id": "9794fe71", + "metadata": { + "id": "9794fe71" + }, + "source": [ + "#### Ejercicio 04: Busca varias formas de generar un array con números aleatorios y crea un array 1D y dos arrays 2D (★★☆)\n", + "\n", + "> NOTA: Revisa las funciones `np.random.rand` (https://numpy.org/doc/stable/reference/random/generated/numpy.random.rand.html), `np.random.randint` (https://numpy.org/doc/stable/reference/random/generated/numpy.random.randint.html) y `np.random.randn` (https://numpy.org/doc/stable/reference/random/generated/numpy.random.randn.html)" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "3d9a48a7", + "metadata": { + "id": "3d9a48a7", + "outputId": "42bf763f-2923-4739-8ec7-0c728bcb756b", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "array([0.52748898, 0.16368871, 0.42269019, 0.91833721, 0.98328199,\n", + " 0.01328715, 0.62057307, 0.10623773, 0.64947961, 0.76615282])" + ] + }, + "metadata": {}, + "execution_count": 32 + } + ], + "source": [ + "import numpy as np\n", + "array1d=np.random.rand(10) #array 1 dimension con random.rand(crear nm aleatorios en tre 0 y 1)\n", + "array1d" + ] + }, + { + "cell_type": "code", + "source": [ + "import numpy as np\n", + "array2d=np.random.randn(3,2) #array 2 dimensiones con random.randn\n", + "array2d\n" + ], + "metadata": { + "id": "wDGj0zmZctA_", + "outputId": "b5d4e2ef-34ec-4201-be46-6370c51fba12", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "id": "wDGj0zmZctA_", + "execution_count": 35, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "array([[-0.09296877, 1.05600624],\n", + " [ 1.48402102, 1.04387293],\n", + " [-0.14238117, 0.50118885]])" + ] + }, + "metadata": {}, + "execution_count": 35 + } + ] + }, + { + "cell_type": "code", + "source": [ + "import numpy as np\n", + "array2d=np.random.randint(0,10,(2,3)) #array 2 dimensiones con randint\n", + "array2d" + ], + "metadata": { + "id": "04VENSc_ZA79", + "outputId": "c0080f1e-c010-42c4-dbf2-b400b823e707", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "id": "04VENSc_ZA79", + "execution_count": 23, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "array([[9, 2, 7],\n", + " [6, 0, 1]])" + ] + }, + "metadata": {}, + "execution_count": 23 + } + ] + }, + { + "cell_type": "markdown", + "id": "78a37e5c", + "metadata": { + "id": "78a37e5c" + }, + "source": [ + "#### Ejercicio 05: Crea una matriz (array 2D) identidad de 5x5 (★☆☆)\n", + "\n", + "\n", + "> NOTA: Revisa la función `np.eye`(https://numpy.org/devdocs/reference/generated/numpy.eye.html)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a6751106", + "metadata": { + "id": "a6751106" + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "08bb63e6", + "metadata": { + "id": "08bb63e6" + }, + "source": [ + "#### Ejercicio 06: Crea una matriz con números aleatorios de 3x2 y calcula el valor mínimo y máximo (★☆☆)\n", + "\n", + "> NOTA: Revisa la función `np.min` (https://numpy.org/devdocs/reference/generated/numpy.min.html) y `np.max` (https://numpy.org/devdocs/reference/generated/numpy.max.html)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3214cca1", + "metadata": { + "id": "3214cca1" + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "57c6c275", + "metadata": { + "id": "57c6c275" + }, + "source": [ + "#### Ejercicio 07: Crea un vector con números aleatorios de 30 elementos y calcula la media (★☆☆)\n", + "\n", + "> NOTA: Revisa la función `np.mean` (https://numpy.org/doc/stable/reference/generated/numpy.mean.html)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cc960ba5", + "metadata": { + "id": "cc960ba5" + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "2c801667", + "metadata": { + "id": "2c801667" + }, + "source": [ + "#### Ejercicio 08: Convierte la lista `[1, 2, 3]` y la tupla `(1, 2, 3)` en arrays (★☆☆)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3f36c71c", + "metadata": { + "id": "3f36c71c" + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "962bb9fc", + "metadata": { + "id": "962bb9fc" + }, + "source": [ + "### Operaciones entre arrays" + ] + }, + { + "cell_type": "markdown", + "id": "48d48f01", + "metadata": { + "id": "48d48f01" + }, + "source": [ + "#### Ejercicio 09: Invierte el vector del ejercicio anterior (★☆☆)\n", + "\n", + "> NOTA: Revisa la función `np.flip` (https://numpy.org/doc/stable/reference/generated/numpy.flip.html)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d3e13052", + "metadata": { + "id": "d3e13052" + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "233addce", + "metadata": { + "id": "233addce" + }, + "source": [ + "#### Ejercicio 10: Cambia el tamaño de un array aleatorio de dimensiones 5x12 en 12x5 (★☆☆)\n", + "\n", + "> NOTA: Revisa la función `np.reshape` (https://numpy.org/doc/stable/reference/generated/numpy.reshape.html)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bfaed09f", + "metadata": { + "id": "bfaed09f" + }, + "outputs": [], + "source": [ + "import numpy as np\n" + ] + }, + { + "cell_type": "markdown", + "id": "645e5381", + "metadata": { + "id": "645e5381" + }, + "source": [ + "#### Ejercicio 11: Convierte la lista `[1, 2, 0, 0, 4, 0]` en un array y obtén el índice de los elementos que no son cero (★★☆)\n", + "\n", + "> NOTA: Revisa la función `np.where` (https://numpy.org/devdocs/reference/generated/numpy.where.html)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b2652fee", + "metadata": { + "id": "b2652fee" + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "e7948dbb", + "metadata": { + "id": "e7948dbb" + }, + "source": [ + "#### Ejercicio 12: Convierte la lista `[0, 5, -1, 3, 15]` en un array, multiplica sus valores por `-2` y obtén los elementos pares (★★☆)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "0oxJ17iDTolQ" + }, + "outputs": [], + "source": [], + "id": "0oxJ17iDTolQ" + }, + { + "cell_type": "markdown", + "id": "a90d6f3e", + "metadata": { + "id": "a90d6f3e" + }, + "source": [ + "#### Ejercicio 13: Crea un vector aleatorio de 10 elementos y ordénalo de menor a mayor (★★☆)\n", + "\n", + "> NOTA: Revisa la función `np.sort` (https://numpy.org/doc/stable/reference/generated/numpy.sort.html)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bc373a83", + "metadata": { + "id": "bc373a83" + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "5e9b6115", + "metadata": { + "id": "5e9b6115" + }, + "source": [ + "#### Ejercicio 14: Genera dos vectores aleatorios de 8 elementos y aplica las operaciones de suma, resta y multiplicación entre ellos (★★☆)\n", + "\n", + "> NOTA: Revisa las funciones matemáticas: https://numpy.org/doc/stable/reference/routines.math.html" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cc77e421", + "metadata": { + "id": "cc77e421" + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "c8e8daa0", + "metadata": { + "id": "c8e8daa0" + }, + "source": [ + "#### Ejercicio 15: Convierte la lista `[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]` en un array y transfórmalo en una matriz con filas de 3 columnas (★★★)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "zH2f_karTolU" + }, + "outputs": [], + "source": [], + "id": "zH2f_karTolU" + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.4" + }, + "colab": { + "provenance": [] + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} \ No newline at end of file