{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "6bb2a88b",
   "metadata": {},
   "source": [
    "# 01 · Estructuras de datos en Python\n",
    "\n",
    "Los bloques con los que se construye cualquier programa en Python: las cuatro colecciones básicas, los\n",
    "contenedores especializados de la biblioteca estándar, las funciones, un primer vistazo a las clases, las\n",
    "comprensiones y el manejo de errores. Cada ejemplo es corto y ejecutable; modifícalo y vuelve a ejecutarlo.\n",
    "\n",
    "**Aprenderás**\n",
    "1. Listas, tuplas, diccionarios y conjuntos, y cuándo usar cada uno\n",
    "2. El módulo `collections`: `deque`, `Counter`, `defaultdict`, `namedtuple`\n",
    "3. Funciones: argumentos por defecto, `*args`, `**kwargs`, lambdas\n",
    "4. Clases en cinco minutos (el módulo 05 profundiza mucho más)\n",
    "5. Comprensiones y generadores\n",
    "6. Excepciones\n",
    "7. Por qué importa la estructura elegida: medir la velocidad de búsqueda"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c739d889",
   "metadata": {},
   "source": [
    "## 1. Listas\n",
    "Ordenadas, **mutables** y admiten duplicados. El contenedor por defecto para \"una secuencia de cosas\"."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "0c0c28ad",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-18T10:07:09.875059Z",
     "iopub.status.busy": "2026-10-18T10:07:09.874471Z",
     "iopub.status.idle": "2026-10-18T10:07:09.893846Z",
     "shell.execute_reply": "2026-10-18T10:07:09.892175Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['apple', 'apricot', 'cherry'] | extraído: date\n",
      "[2, 3, 4] [0, 2, 4, 6, 8] [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]\n",
      "['Fig', 'apple', 'pear'] ['apple', 'Fig', 'pear'] ['apple', 'pear', 'Fig']\n"
     ]
    }
   ],
   "source": [
    "fruits = [\"apple\", \"banana\", \"cherry\"]\n",
    "fruits.append(\"date\")             # añadir al final\n",
    "fruits.insert(1, \"apricot\")       # añadir en una posición\n",
    "fruits.remove(\"banana\")           # quitar el primer valor que coincida\n",
    "last = fruits.pop()               # quitar y devolver el último elemento\n",
    "print(fruits, \"| extraído:\", last)\n",
    "\n",
    "# rebanadas: [inicio:fin:paso], el fin no se incluye\n",
    "nums = list(range(10))\n",
    "print(nums[2:5], nums[::2], nums[::-1])\n",
    "\n",
    "# ordenar: sorted() devuelve una lista nueva, .sort() ordena en el sitio\n",
    "words = [\"pear\", \"Fig\", \"apple\"]\n",
    "print(sorted(words), sorted(words, key=str.lower), sorted(words, key=len, reverse=True))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f6d795b0",
   "metadata": {},
   "source": [
    "## 2. Tuplas\n",
    "Ordenadas e **inmutables**. Úsalas para grupos fijos de valores (un punto, una fila de una base de datos) y\n",
    "para devolver varios valores desde una función. Al ser inmutables, pueden ser claves de un diccionario o\n",
    "elementos de un conjunto."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "5dc10a88",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-18T10:07:09.899978Z",
     "iopub.status.busy": "2026-10-18T10:07:09.899425Z",
     "iopub.status.idle": "2026-10-18T10:07:09.910448Z",
     "shell.execute_reply": "2026-10-18T10:07:09.908394Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(3, 4) ('only_one',) 3 4\n",
      "2 9\n",
      "1 [2, 3, 4] 5\n"
     ]
    }
   ],
   "source": [
    "point = (3, 4)\n",
    "single = (\"only_one\",)            # la coma final la convierte en tupla\n",
    "x, y = point                      # desempaquetado\n",
    "print(point, single, x, y)\n",
    "\n",
    "def min_max(values):\n",
    "    return min(values), max(values)   # devuelve una tupla\n",
    "\n",
    "lo, hi = min_max([7, 2, 9, 4])\n",
    "print(lo, hi)\n",
    "\n",
    "first, *middle, last = [1, 2, 3, 4, 5]   # desempaquetado extendido\n",
    "print(first, middle, last)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4d70553d",
   "metadata": {},
   "source": [
    "## 3. Diccionarios\n",
    "Pares clave-valor, mutables y ordenados por inserción desde Python 3.7. Buscar por clave es rápido, sea cual\n",
    "sea el tamaño del diccionario."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "c89aad48",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-18T10:07:09.915562Z",
     "iopub.status.busy": "2026-10-18T10:07:09.915047Z",
     "iopub.status.idle": "2026-10-18T10:07:09.925789Z",
     "shell.execute_reply": "2026-10-18T10:07:09.923729Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "n/d\n",
      "  name: Alice\n",
      "   age: 31\n",
      "  city: Berlin\n",
      " email: alice@example.com\n",
      "{'city': 'Berlin', 'active': True, 'name': 'Alice', 'age': 31, 'email': 'alice@example.com'} {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}\n"
     ]
    }
   ],
   "source": [
    "person = {\"name\": \"Alice\", \"age\": 30, \"city\": \"Berlin\"}\n",
    "person[\"age\"] = 31                       # actualizar\n",
    "person[\"email\"] = \"alice@example.com\"    # añadir\n",
    "print(person.get(\"phone\", \"n/d\"))        # acceso seguro con valor por defecto\n",
    "for key, value in person.items():\n",
    "    print(f\"{key:>6}: {value}\")\n",
    "\n",
    "# combinar diccionarios y comprensiones de diccionario\n",
    "defaults = {\"city\": \"Unknown\", \"active\": True}\n",
    "merged = defaults | person               # gana el de la derecha (Python 3.9+)\n",
    "squares = {n: n * n for n in range(5)}\n",
    "print(merged, squares)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "44b97587",
   "metadata": {},
   "source": [
    "## 4. Conjuntos\n",
    "Sin orden, mutables y con elementos **únicos**. Ideales para comprobar pertenencia y eliminar duplicados."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "b01c67e1",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-18T10:07:09.930716Z",
     "iopub.status.busy": "2026-10-18T10:07:09.930160Z",
     "iopub.status.idle": "2026-10-18T10:07:09.940002Z",
     "shell.execute_reply": "2026-10-18T10:07:09.937998Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{1, 2, 3, 4, 5} {3} {1, 2} {1, 2, 4, 5}\n",
      "[1, 2, 3]\n",
      "True frozenset({1, 2, 3})\n"
     ]
    }
   ],
   "source": [
    "a, b = {1, 2, 3}, {3, 4, 5}\n",
    "print(a | b, a & b, a - b, a ^ b)        # unión, intersección, diferencia, diferencia simétrica\n",
    "\n",
    "nums = [1, 2, 2, 3, 3, 3]\n",
    "print(sorted(set(nums)))                 # deduplicar (los conjuntos no guardan orden: ordena si lo necesitas)\n",
    "print(3 in a, frozenset(a))              # frozenset: conjunto inmutable, sirve como clave de diccionario"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8f6885e5",
   "metadata": {},
   "source": [
    "## 5. Contenedores especializados: `collections`\n",
    "La biblioteca estándar trae estructuras listas para patrones comunes. Usarlas acorta el código y a menudo\n",
    "lo hace más rápido.\n",
    "\n",
    "| Estructura | Úsala para |\n",
    "|---|---|\n",
    "| `deque` | colas y ventanas deslizantes: añadir y quitar rápido por **ambos** extremos |\n",
    "| `Counter` | contar cosas |\n",
    "| `defaultdict` | agrupar sin comprobaciones del tipo \"si la clave no está en el diccionario\" |\n",
    "| `namedtuple` | registros ligeros con campos con nombre |\n",
    "| `heapq` (módulo) | obtener siempre el elemento más pequeño: colas de prioridad, los k mejores |"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "3b68dff2",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-18T10:07:09.944641Z",
     "iopub.status.busy": "2026-10-18T10:07:09.944171Z",
     "iopub.status.idle": "2026-10-18T10:07:09.958001Z",
     "shell.execute_reply": "2026-10-18T10:07:09.956210Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "últimas 3 lecturas: [11, 15, 14] media: 13.333333333333334\n",
      "[('the', 3), ('quick', 1)]\n",
      "{'a': ['apple', 'avocado'], 'b': ['banana', 'blueberry'], 'c': ['cherry']}\n",
      "[City(name='Tokyo', population_m=37.4), City(name='Delhi', population_m=32.9)]\n"
     ]
    }
   ],
   "source": [
    "from collections import deque, Counter, defaultdict, namedtuple\n",
    "import heapq\n",
    "\n",
    "window = deque(maxlen=3)                 # guarda solo los 3 últimos elementos\n",
    "for reading in [10, 12, 11, 15, 14]:\n",
    "    window.append(reading)\n",
    "print(\"últimas 3 lecturas:\", list(window), \"media:\", sum(window) / len(window))\n",
    "\n",
    "text = \"the quick brown fox jumps over the lazy dog the end\"\n",
    "print(Counter(text.split()).most_common(2))\n",
    "\n",
    "by_letter = defaultdict(list)\n",
    "for word in [\"apple\", \"avocado\", \"banana\", \"blueberry\", \"cherry\"]:\n",
    "    by_letter[word[0]].append(word)\n",
    "print(dict(by_letter))\n",
    "\n",
    "City = namedtuple(\"City\", [\"name\", \"population_m\"])\n",
    "cities = [City(\"Tokyo\", 37.4), City(\"Delhi\", 32.9), City(\"Shanghai\", 29.2), City(\"Madrid\", 6.8)]\n",
    "print(heapq.nlargest(2, cities, key=lambda c: c.population_m))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "801ac22b",
   "metadata": {},
   "source": [
    "## 6. Funciones\n",
    "Bloques de código reutilizables. Las anotaciones de tipo documentan qué entra y qué sale; Python no las\n",
    "comprueba al ejecutar, pero los editores y herramientas como `mypy` sí las usan."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "fc82870e",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-18T10:07:09.961516Z",
     "iopub.status.busy": "2026-10-18T10:07:09.961190Z",
     "iopub.status.idle": "2026-10-18T10:07:09.971684Z",
     "shell.execute_reply": "2026-10-18T10:07:09.969024Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello, Alice! Hi, Bob!\n",
      "6 | colour=red, size=M\n",
      "[1, 4, 9] ['ccc', 'bb', 'a']\n"
     ]
    }
   ],
   "source": [
    "def greet(name: str, greeting: str = \"Hello\") -> str:\n",
    "    return f\"{greeting}, {name}!\"\n",
    "\n",
    "print(greet(\"Alice\"), greet(\"Bob\", greeting=\"Hi\"))\n",
    "\n",
    "def total(*args: float) -> float:          # cualquier número de argumentos posicionales\n",
    "    return sum(args)\n",
    "\n",
    "def describe(**kwargs) -> str:             # cualquier número de argumentos con nombre\n",
    "    return \", \".join(f\"{k}={v}\" for k, v in kwargs.items())\n",
    "\n",
    "print(total(1, 2, 3), \"|\", describe(colour=\"red\", size=\"M\"))\n",
    "\n",
    "square = lambda n: n ** 2                   # pequeña función anónima\n",
    "print(list(map(square, [1, 2, 3])), sorted([\"bb\", \"a\", \"ccc\"], key=lambda s: -len(s)))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0965faf1",
   "metadata": {},
   "source": [
    "**Una trampa clásica: argumentos por defecto mutables.** El valor por defecto se crea una sola vez, al\n",
    "definir la función, no en cada llamada."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "861aa97b",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-18T10:07:09.976498Z",
     "iopub.status.busy": "2026-10-18T10:07:09.976090Z",
     "iopub.status.idle": "2026-10-18T10:07:09.984886Z",
     "shell.execute_reply": "2026-10-18T10:07:09.983077Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['a', 'b'] ['a', 'b']\n",
      "['a'] ['b']\n"
     ]
    }
   ],
   "source": [
    "def add_item_bad(item, items=[]):\n",
    "    items.append(item)\n",
    "    return items\n",
    "\n",
    "def add_item_good(item, items=None):\n",
    "    items = [] if items is None else items\n",
    "    items.append(item)\n",
    "    return items\n",
    "\n",
    "print(add_item_bad(\"a\"), add_item_bad(\"b\"))     # se reutiliza la misma lista: ['a', 'b'] dos veces\n",
    "print(add_item_good(\"a\"), add_item_good(\"b\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "21769c73",
   "metadata": {},
   "source": [
    "## 7. Clases en cinco minutos\n",
    "Una clase es un plano, un objeto es una instancia de ella y los métodos son funciones que pertenecen a la\n",
    "clase. El módulo 05 trata la programación orientada a objetos a fondo; esto es lo justo para leer código que\n",
    "la usa."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "4dbbb1b7",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-18T10:07:09.989271Z",
     "iopub.status.busy": "2026-10-18T10:07:09.988846Z",
     "iopub.status.idle": "2026-10-18T10:07:09.998705Z",
     "shell.execute_reply": "2026-10-18T10:07:09.996730Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Dog(name='Rex', age=4) Rex dice guau Canis familiaris\n"
     ]
    }
   ],
   "source": [
    "class Dog:\n",
    "    species = \"Canis familiaris\"            # atributo de clase: compartido por todos los perros\n",
    "\n",
    "    def __init__(self, name: str, age: int):\n",
    "        self.name = name                    # atributos de instancia: uno por perro\n",
    "        self.age = age\n",
    "\n",
    "    def speak(self) -> str:\n",
    "        return f\"{self.name} dice guau\"\n",
    "\n",
    "    def __repr__(self) -> str:              # cómo se imprime el objeto\n",
    "        return f\"Dog(name={self.name!r}, age={self.age})\"\n",
    "\n",
    "rex = Dog(\"Rex\", 4)\n",
    "print(rex, rex.speak(), Dog.species)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f65cc32a",
   "metadata": {},
   "source": [
    "## 8. Comprensiones y generadores\n",
    "Las comprensiones construyen una colección en una línea legible. Un **generador** produce los valores bajo\n",
    "demanda, uno a uno, así que apenas usa memoria aunque sean millones de elementos. La idea reaparece en el\n",
    "módulo 03."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "18a8135b",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-18T10:07:10.005400Z",
     "iopub.status.busy": "2026-10-18T10:07:10.004757Z",
     "iopub.status.idle": "2026-10-18T10:07:10.165432Z",
     "shell.execute_reply": "2026-10-18T10:07:10.163183Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0, 4, 16, 36, 64] [(0, 'a'), (0, 'b'), (1, 'a'), (1, 'b'), (2, 'a'), (2, 'b')]\n",
      "lista: 8.4 MB, generador: 192 bytes\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "suma desde el generador: 499999500000\n",
      "[5, 4, 3, 2, 1]\n"
     ]
    }
   ],
   "source": [
    "import sys\n",
    "\n",
    "squares = [n ** 2 for n in range(10) if n % 2 == 0]\n",
    "pairs = [(x, y) for x in range(3) for y in \"ab\"]\n",
    "print(squares, pairs)\n",
    "\n",
    "big_list = [n for n in range(1_000_000)]\n",
    "big_gen = (n for n in range(1_000_000))\n",
    "print(f\"lista: {sys.getsizeof(big_list) / 1e6:.1f} MB, generador: {sys.getsizeof(big_gen)} bytes\")\n",
    "print(\"suma desde el generador:\", sum(big_gen))\n",
    "\n",
    "def countdown(n):\n",
    "    while n > 0:\n",
    "        yield n          # 'yield' convierte esta función en un generador\n",
    "        n -= 1\n",
    "\n",
    "print(list(countdown(5)))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7a9675dd",
   "metadata": {},
   "source": [
    "## 9. Excepciones\n",
    "Gestiona los errores que esperas y deja que los inesperados salgan a la luz. `else` solo se ejecuta si nada\n",
    "falló; `finally` se ejecuta siempre (limpieza)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "cd6a3f04",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-18T10:07:10.169745Z",
     "iopub.status.busy": "2026-10-18T10:07:10.169312Z",
     "iopub.status.idle": "2026-10-18T10:07:10.179564Z",
     "shell.execute_reply": "2026-10-18T10:07:10.177636Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "divide(10, 2) terminado\n",
      "no se puede dividir entre cero\n",
      "divide(1, 0) terminado\n",
      "entrada no válida: unsupported operand type(s) for /: 'str' and 'int'\n",
      "divide('a', 1) terminado\n",
      "5.0 None None\n",
      "capturada: saldo 10, solicitado 50\n"
     ]
    }
   ],
   "source": [
    "def divide(a, b):\n",
    "    try:\n",
    "        result = a / b\n",
    "    except ZeroDivisionError:\n",
    "        print(\"no se puede dividir entre cero\")\n",
    "        return None\n",
    "    except TypeError as e:\n",
    "        print(\"entrada no válida:\", e)\n",
    "        return None\n",
    "    else:\n",
    "        return result\n",
    "    finally:\n",
    "        print(f\"divide({a!r}, {b!r}) terminado\")\n",
    "\n",
    "print(divide(10, 2), divide(1, 0), divide(\"a\", 1))\n",
    "\n",
    "class InsufficientFunds(Exception):\n",
    "    '''Una excepción propia deja explícito el fallo a quien llama.'''\n",
    "\n",
    "try:\n",
    "    raise InsufficientFunds(\"saldo 10, solicitado 50\")\n",
    "except InsufficientFunds as e:\n",
    "    print(\"capturada:\", e)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6f535e41",
   "metadata": {},
   "source": [
    "## 10. Por qué importa la estructura elegida\n",
    "Comprobar si un elemento está **en** una lista la recorre elemento a elemento (el tiempo crece con el tamaño,\n",
    "O(n)). Un conjunto o un diccionario usa hashing y responde en aproximadamente el mismo tiempo sea cual sea\n",
    "su tamaño (O(1) en promedio). Medido:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "77189fa4",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-18T10:07:10.184042Z",
     "iopub.status.busy": "2026-10-18T10:07:10.183668Z",
     "iopub.status.idle": "2026-10-18T10:07:13.454830Z",
     "shell.execute_reply": "2026-10-18T10:07:13.452063Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "n=    1,000  lista:       13.1 µs   conjunto:   0.15 µs\n",
      "n=   10,000  lista:      132.6 µs   conjunto:   0.14 µs\n",
      "n=  100,000  lista:     1370.3 µs   conjunto:   0.15 µs\n",
      "n=1,000,000  lista:    14007.4 µs   conjunto:   0.16 µs\n"
     ]
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 600x350 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import timeit\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "sizes = [1_000, 10_000, 100_000, 1_000_000]\n",
    "t_list, t_set = [], []\n",
    "for n in sizes:\n",
    "    data_list = list(range(n))\n",
    "    data_set = set(data_list)\n",
    "    target = n - 1                          # peor caso para la lista: el último elemento\n",
    "    t_list.append(timeit.timeit(lambda: target in data_list, number=50) / 50 * 1e6)\n",
    "    t_set.append(timeit.timeit(lambda: target in data_set, number=50) / 50 * 1e6)\n",
    "\n",
    "for n, a, b in zip(sizes, t_list, t_set):\n",
    "    print(f\"n={n:>9,}  lista: {a:10.1f} µs   conjunto: {b:6.2f} µs\")\n",
    "\n",
    "plt.figure(figsize=(6, 3.5))\n",
    "plt.loglog(sizes, t_list, \"o-\", label=\"lista (O(n))\")\n",
    "plt.loglog(sizes, t_set, \"s-\", label=\"conjunto (O(1))\")\n",
    "plt.xlabel(\"número de elementos\"); plt.ylabel(\"tiempo por búsqueda (µs)\"); plt.legend(); plt.title(\"Prueba de pertenencia\")\n",
    "plt.tight_layout(); plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9a695c28",
   "metadata": {},
   "source": [
    "| Operación | list | tuple | dict | set |\n",
    "|---|---|---|---|---|\n",
    "| ordenado | sí | sí | sí (inserción) | no |\n",
    "| mutable | sí | no | sí | sí |\n",
    "| duplicados | sí | sí | claves únicas | no |\n",
    "| `x in c` | O(n) | O(n) | O(1) en claves | O(1) |\n",
    "| uso típico | secuencias | registros fijos | búsquedas por clave | pertenencia, deduplicar |\n",
    "\n",
    "## Ejercicios\n",
    "1. Dada una lista de palabras, devuelve las cinco más frecuentes con su recuento (una línea con `Counter`).\n",
    "2. Agrupa una lista de tuplas `(alumno, nota)` en un diccionario `nota -> [alumnos]` con `defaultdict`.\n",
    "3. Escribe un generador `fibonacci()` que produzca la sucesión indefinidamente e imprime los 15 primeros valores con `itertools.islice`.\n",
    "4. Repite el experimento de tiempos con un `dict` y una `tuple`. ¿Cuál se comporta como una lista y cuál como un conjunto?"
   ]
  }
 ],
 "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.12.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
