Estructuras de Datos y Proyecto Final

3.01 · Arreglos Unidimensionales (Vectores)

PF-301 ⏱ 90 min ⭐ 100 XP intermedio

🎯 Objetivo de aprendizaje

Al terminar este tema vas a poder:

  1. Explicar qué es un arreglo 1D y por qué es la estructura de datos más usada en programación.
  2. Declarar arreglos en C++: int nums[10];, int nums[] = {1, 2, 3};, const int MAX = 5;.
  3. Acceder a elementos individuales con el operador [] y entender el sistema de índices 0-based.
  4. Recorrer arreglos con for para leer, escribir, buscar y procesar.
  5. Visualizar cómo se almacenan los arreglos en la memoria RAM (contigua, indexada).
  6. Implementar los algoritmos clásicos: búsqueda lineal, suma, mayor/menor, inversión.
  7. Validar los índices antes de acceder (evitar acceso fuera de rango).
  8. Trabajar con arreglos de cualquier tipo de dato: int, double, char, string.

Los arreglos son la base del 90% de los algoritmos. Sin ellos, no podrías procesar una lista de alumnos, una hoja de cálculo, ni un catálogo de productos. Dominar los arreglos es dominar la base de la programación.

🧠 Teoría y conceptos — 3.1.1 — El problema: ¿qué pasa con muchas variables?

El problema: ¿qué pasa con muchas variables?
El problema: ¿qué pasa con muchas variables?

El límite de las variables sueltas

Hasta ahora, cada dato que querías guardar necesitaba su propia variable:

int nota1, nota2, nota3, nota4, nota5; // 5 calificaciones

Pero, ¿qué pasa con 30 calificaciones? ¿100? ¿1 millón? Escribir 1 millón de variables es imposible.

La solución: el arreglo

Un arreglo (o vector en C++ moderno) es una colección de variables del mismo tipo, almacenadas en posiciones contiguas de memoria, accesibles por un índice numérico.

Analogía: la caja de casilleros de un gimnasio. Todos los casilleros son iguales (mismo tamaño, misma forma), están numerados del 0 al N-1, y puedes meter/retirar cosas de cualquiera de ellos por su número.

Figura: Analogía: variable vs arreglo

Una variable es como un casillero individual; un arreglo es una fila entera de casilleros numerados.

Figura: Analogía: arreglo de 6 casilleros

Un arreglo de 6 elementos. Cada casillero tiene un número (índice) y guarda un valor del mismo tipo.

Cuaderno físico (obligatorio)

la diferencia entre una variable suelta y un arreglo. Da 3 ejemplos de la vida real donde necesitarías un arreglo (no variables sueltas).

3.1.2 — ¿Qué es un arreglo? La caja de casilleros

¿Qué es un arreglo? La caja de casilleros
¿Qué es un arreglo? La caja de casilleros

Definición formal

Un arreglo es una estructura de datos que almacena una colección de elementos del mismo tipo en posiciones contiguas de memoria, identificadas por un índice numérico (0, 1, 2, ..., N-1).

Por qué importa el orden 0-based

En C++ (y Java, C, Python, JavaScript), el primer elemento es el índice 0, no el 1. Esto es por convención: nums[0] es el primero.

¿Por qué? Por la forma en que la memoria direcciona: el primer elemento está en la dirección base, el segundo en base+1*sizeof(tipo), etc. Empezar en 0 simplifica el cálculo.

Cuaderno físico (obligatorio)

¿por qué los índices empiezan en 0 en la mayoría de lenguajes? Investiga y escribe tu respuesta.

3.1.3 — Declaración, inicialización y acceso por índice

Declaración, inicialización y acceso por índice
Declaración, inicialización y acceso por índice

Las 3 formas de declarar

Forma 1: declarar sin inicializar (valores basura):

int notas[5]; // 5 enteros, valores indefinidos (basura de memoria)

Forma 2: declarar e inicializar con valores:

int notas[5] = {85, 90, 78, 92, 88};  // 5 enteros, valores específicos

Forma 3: declarar sin tamaño específico (lo deduce el compilador):

int notas[] = {85, 90, 78, 92, 88};  // 5 elementos (lo deduce)

Forma 4: con constante simbólica (mejor práctica):

const int MAX_ALUMNOS = 30;

int notas[MAX_ALUMNOS]; // Usa la constante

Visualización del arreglo declarado

Figura: Declaración de un arreglo

Arreglo `int nums[5] = {10, 20, 30, 40, 50}` con 5 celdas, cada una accesible por su índice.

Acceso por índice

int nums[5] = {10, 20, 30, 40, 50};
cout << nums[0];   // Imprime 10 (primer elemento)
cout << nums[2];   // Imprime 30 (tercer elemento)
cout << nums[4];   // Imprime 50 (último elemento)

nums[0] = 100; // Cambia el primer elemento a 100

Figura: Acceso por índice

Acceso por índice: `nums[0]` da el primer elemento, `nums[4]` el último.

Reglas de oro

  • El primer índice es 0, no 1.
  • El último índice es N-1 (tamaño menos 1).
  • Acceder fuera de rango (nums[5] en un arreglo de 5) es comportamiento indefinido (puede crashear o dar basura).

Errores comunes

int nums[5] = {10, 20, 30, 40, 50};

// ❌ MAL: empieza en 1 (índice fuera de rango)

cout << nums[1];   // Imprime 20, no 10

// Si el usuario esperaba "el primer elemento", se confunde

// ❌ MAL: índice fuera de rango

cout << nums[5];   // Comportamiento indefinido (basura o crash)

// ❌ MAL: confundir el índice con el valor

int i = 3;

cout << nums[i];   // ✅ Esto SÍ es correcto: imprime 40

// Confundir el 3 con "el tercer elemento" es un error de comprensión

Cuaderno físico (obligatorio)

las 3 reglas de oro (índice 0, último = N-1, sin acceso fuera de rango) y los 3 errores comunes. Memorízalos.

3.1.4 — Cómo se almacenan los arreglos en memoria

Cómo se almacenan los arreglos en memoria
Cómo se almacenan los arreglos en memoria

La memoria RAM como una fila de casilleros

La memoria RAM se puede imaginar como una secuencia enorme de casilleros numerados, cada uno con una dirección única. Un byte = un casillero. Cada casillero tiene una dirección (por ejemplo, 0x7FFE0001).

Cuando declaras int nums[5] = {10, 20, 30, 40, 50};, el sistema operativo reserva 5 casilleros contiguos en la RAM (5 × 4 bytes = 20 bytes, porque un int ocupa 4 bytes).

Diagrama de los segmentos de memoria

Figura: Segmentos de memoria

Segmentos típicos de un programa en C++. El arreglo `nums[5]` se almacena en el stack (junto con las variables locales), en posiciones contiguas de memoria.

La fórmula de direccionamiento

Si nums empieza en la dirección 0x1000 y cada int ocupa 4 bytes:

Fórmula: dirección_de_nums[i] = dirección_base + i * sizeof(tipo)

Por qué importa

  • Acceso O(1): acceder a nums[i] toma el mismo tiempo sin importar i. El hardware calcula la dirección con la fórmula y la lee. No tiene que recorrer desde el principio.
  • Localidad de caché: como los elementos están contiguos, cuando accedes a nums[0] el CPU trae también nums[1], nums[2], etc. a la caché, así que los accesos siguientes son más rápidos.
  • Acceso fuera de rango = peligro: si intentas acceder a nums[10] en un arreglo de 5, el sistema no sabe que es tu error; lee 20 bytes más allá de tu arreglo, que pueden ser datos de otra variable. Comportamiento indefinido.
Cuaderno físico (obligatorio)

los 4 puntos clave sobre la memoria de los arreglos: contigüidad, acceso O(1), localidad de caché, peligro de fuera de rango.

3.1.5 — Recorrido con for: leer, escribir, procesar

Recorrido con for: leer, escribir, procesar
Recorrido con for: leer, escribir, procesar

El patrón fundamental

El 90% de las operaciones con arreglos se hacen con un for que recorre índice por índice:

const int N = 5;

int nums[N] = {10, 20, 30, 40, 50};

// RECORRIDO: pasar por todos los elementos uno por uno

for (int i = 0; i < N; i++) {  // i va de 0 a N-1
cout << nums[i] << " ";

}

// Imprime: 10 20 30 40 50

Figura: Recorrido del arreglo

El bucle `for` recorre el arreglo índice por índice. `i` es el "dedo" que va señalando cada celda.

Las 4 operaciones básicas con for

  1. Leer (imprimir):
for (int i = 0; i < N; i++) {
cout << "nums[" << i << "] = " << nums[i] << endl;

}

  1. Escribir (llenar desde el usuario):
for (int i = 0; i < N; i++) {
cout << "Ingresa el valor " << (i+1) << ": ";
cin >> nums[i];

}

  1. Procesar (calcular suma):

int suma = 0;

for (int i = 0; i < N; i++) {

suma += nums[i];

}

cout << "Suma: " << suma << endl;
  1. Buscar:

int objetivo = 30;

int posicion = -1;

for (int i = 0; i < N; i++) {
if (nums[i] == objetivo) {

posicion = i;

break; // Salir al encontrar

}

}

if (posicion != -1) {
cout << "Encontrado en posición " << posicion << endl;
} else {
cout << "No encontrado" << endl;

}

Cuaderno físico (obligatorio)

el patrón fundamental `for (int i = 0; i < N; i++)`. Memorízalo: lo vas a usar 1000 veces.

3.1.6 — Validación de índices (evitar bugs comunes)

Validación de índices (evitar bugs comunes)
Validación de índices (evitar bugs comunes)

El error #1: acceso fuera de rango

const int N = 5;

int nums[N] = {10, 20, 30, 40, 50};

// ❌ PELIGROSO: accede a memoria fuera del arreglo

cout << nums[5];   // Índice 5 no existe (último válido es 4)
cout << nums[100]; // Muy fuera, comportamiento impredecible

¿Por qué es peligroso? El programa no avisa. Lee lo que esté en esa posición de memoria (basura, otra variable, etc.). Puede crashear o dar resultados incorrectos silenciosamente.

La regla: validar SIEMPRE

// ✅ BIEN: validar antes de acceder

int i;

cout << "Índice: "; cin >> i;
if (i >= 0 && i < N) {
cout << "Valor: " << nums[i] << endl;
} else {
cout << "Índice fuera de rango" << endl;

}

En bucles: usar < N o <= N-1

// ✅ BIEN: < N evita el off-by-one

for (int i = 0; i < N; i++) {  // i: 0, 1, 2, 3, 4
cout << nums[i];

}

// ❌ MAL: <= N causa acceso fuera de rango

for (int i = 0; i <= N; i++) {  // i: 0, 1, 2, 3, 4, 5 (¡fuera!)
cout << nums[i];

}

Cuaderno físico (obligatorio)

la regla `< N` (NO `<= N`). Memorízala: previene el 90% de los bugs de acceso a arreglos.

3.1.7 — Algoritmos clásicos con arreglos

Algoritmo 1: Suma y promedio

const int N = 5;

int nums[N] = {85, 90, 78, 92, 88};

int suma = 0;

for (int i = 0; i < N; i++) {

suma += nums[i];

}

double promedio = (double)suma / N;

cout << "Suma: " << suma << endl;
cout << "Promedio: " << promedio << endl;

Algoritmo 2: Mayor y menor (con inicialización correcta)

const int N = 5;

int nums[N] = {85, 90, 78, 92, 88};

// Inicializar con el PRIMER elemento (no con 0)

int mayor = nums[0];

int menor = nums[0];

for (int i = 1; i < N; i++) {
if (nums[i] > mayor) mayor = nums[i];
if (nums[i] < menor) menor = nums[i];

}

cout << "Mayor: " << mayor << endl;
cout << "Menor: " << menor << endl;

Algoritmo 3: Búsqueda lineal

Figura: Búsqueda lineal

Búsqueda lineal: recorremos uno por uno hasta encontrar el valor. Aquí, el 15 está en la posición 3.

const int N = 7;

int nums[N] = {5, 12, 8, 23, 17, 9, 30};

int objetivo = 23;

int posicion = -1;

for (int i = 0; i < N; i++) {
if (nums[i] == objetivo) {

posicion = i;

break;

}

}

if (posicion != -1) {
cout << "Encontrado en posición " << posicion << endl;
} else {
cout << "No encontrado" << endl;

}

Algoritmo 4: Inversión del arreglo

const int N = 5;

int nums[N] = {1, 2, 3, 4, 5};

// Intercambiar nums[i] con nums[N-1-i] hasta la mitad

for (int i = 0; i < N / 2; i++) {

int temp = nums[i];

nums[i] = nums[N - 1 - i];

nums[N - 1 - i] = temp;

}

// nums ahora es {5, 4, 3, 2, 1}

Algoritmo 5: Encontrar duplicados

const int N = 7;

int nums[N] = {5, 12, 8, 23, 12, 9, 5};

bool hayDuplicados = false;

for (int i = 0; i < N - 1; i++) {
for (int j = i + 1; j < N; j++) {
if (nums[i] == nums[j]) {
cout << "Duplicado encontrado: " << nums[i] << endl;

hayDuplicados = true;

}

}

}

if (!hayDuplicados) {
cout << "No hay duplicados" << endl;

}

Cuaderno físico (obligatorio)

los 5 algoritmos clásicos (suma, mayor/menor, búsqueda, inversión, duplicados) con tu implementación. Memorízalos.

⚠️ Errores típicos — ❌ Errores típicos del razonamiento

Error 1: "El primer elemento es nums[1]"

Idea equivocada: en algunos lenguajes (MATLAB, Lua, R) los arreglos empiezan en 1, así que en C++ también.

Realidad: en C++, Java, C#, Python, JavaScript, el primer elemento es [0]. Acostumbrarse a esto desde el principio.

Cómo evitarlo: siempre escribe arr[0] para el primero, arr[N-1] para el último.

Error 2: "El for debe ir de 1 a N"

Idea equivocada: "es más natural contar desde 1".

Realidad: en C++ (y la mayoría de lenguajes), los arreglos van de 0 a N-1. Un for (int i = 1; i <= N; i++) salta el primer elemento y accede fuera de rango al final.
Cómo evitarlo: siempre for (int i = 0; i < N; i++).

Error 3: "Si el programa no crashea, no hay error"

Idea equivocada: "accedí a nums[10] en un arreglo de 5 y no crasheó, así que está bien".

Realidad: comportamiento indefinido significa que el programa PUEDE crashear, PUEDE dar basura, o PUEDE parecer que funciona. No significa que esté bien. En otro sistema operativo, con otro compilador, en otro momento, va a fallar.

Cómo evitarlo: validar SIEMPRE los índices antes de acceder.

Error 4: "El tamaño del arreglo se puede cambiar en tiempo de ejecución"

Idea equivocada: "el usuario me dijo 10, pero después me dijo 100, así que cambio el tamaño del arreglo".

Realidad: en C++ los arreglos estáticos tienen tamaño fijo al compilar. Para tamaños dinámicos, necesitas arreglos dinámicos (new/delete, Tema 3.4) o vectores (std::vector, Tema 3.5).

Cómo evitarlo: usa una constante simbólica (const int MAX = 100;) y limita el tamaño al inicio.

Error 5: "Mayor = 0 funciona si todos los números son positivos"

Idea equivocada: "siempre inicializo con 0 porque mis datos son calificaciones".

Realidad: si un día los datos son números negativos, "mayor = 0" da el resultado incorrecto. La regla universal es: inicializa con el primer elemento.

Cómo evitarlo: mayor = nums[0] o menor = nums[0]. SIEMPRE.

🤖 IA como copiloto — 🤖 AI Mission 3.1 — Arreglos con IA

Regla de los 3 minutos (obligatoria): primero intenta por tu cuenta, después la IA con prompts específicos.

Prompts sugeridos

Prompt 1 — Detectar bug en un arreglo:

"Te voy a pegar un programa en C++ que accede a un arreglo. NO me lo corrijas. Solo dime: (1) qué hace, (2) si hay acceso fuera de rango, (3) en qué línea. Máximo 100 palabras."

Prompt 2 — Convertir a función:

"Te voy a pegar código que recorre un arreglo. NO me lo conviertas a función. Solo dime: (1) qué hace, (2) si se puede extraer a una función, (3) qué nombre le pondrías. Máximo 100 palabras."

Prompt 3 — Comparar rendimiento:

"Tengo un programa que busca un valor en un arreglo de 1 millón de elementos. ¿Es eficiente la búsqueda lineal? Dame 3 razones por las que sí o por las que no. Sin código, máximo 150 palabras."

Prompt 4 — Generar datos de prueba:

"Necesito 5 arreglos de prueba para un programa de calificaciones. Dame: (1) un arreglo normal, (2) uno con todos 10s, (3) uno con todos 0s, (4) uno con un solo valor, (5) uno con notas negativas. Para cada uno, dame los 5 valores y dime qué resultado esperarías. No me des código. Máximo 200 palabras."

🧪 Laboratorio — 🧪 LAB 3.1 — 6 ejercicios de arreglos 1D

Tiempo total: 1 h 30 min | Entregable: 6 programas funcionando con sus pruebas.

🛠️ Herramienta recomendada para los diagramas de flujo de este LAB: Para los ejercicios que pidan un diagrama de flujo, usa [draw.io (diagrams.net)](https://app.diagrams.net/) — herramienta gratis, sin registro, que funciona en el navegador. Tiene plantillas con la simbología ANSI/ISO lista (en `General → Flowchart`). Exporta tus diagramas como PNG e insértalos en tu cuaderno digital o entrégalos junto con el código.

Ejercicio 1 — Declarar y mostrar (básico, 10 min)

Enunciado. Declara un arreglo de 5 enteros, inicialízalo con valores, e imprímelo en formato índice: valor (uno por línea). Haz un diagrama de flujo clásico del proceso.

Rúbrica (10 pts): declaración correcta (2 pts) + inicialización (2 pts) + recorrido (3 pts) + formato (2 pts) + diagrama (1 pt).

Ejercicio 2 — Suma, promedio, mayor y menor (básico, 20 min)

Enunciado. Dado un arreglo de 10 calificaciones, calcula y muestra: suma, promedio (con 2 decimales), calificación más alta y más baja. Inicializa mayor y menor con el primer elemento.

Rúbrica (10 pts): suma (2 pts) + promedio (2 pts) + mayor (2 pts) + menor (2 pts) + formato (2 pts).

Ejercicio 3 — Búsqueda lineal (intermedio, 20 min)

Enunciado. Pide al usuario un valor a buscar. Recorre el arreglo y di si está, y en qué posición. Si hay duplicados, di TODAS las posiciones. Valida que el índice esté en rango.

Rúbrica (10 pts): búsqueda simple (3 pts) + duplicados (3 pts) + validación (2 pts) + mensajes (2 pts).

Ejercicio 4 — Inversión del arreglo (intermedio, 20 min)

Enunciado. Pide 5 números, guárdalos en un arreglo, e inviértelos (sin usar un segundo arreglo). Muestra el original y el invertido. Dibuja el diagrama de flujo del algoritmo de inversión.

Rúbrica (10 pts): algoritmo correcto (4 pts) + dibujo del diagrama (3 pts) + mensajes (2 pts) + verificación (1 pt).

Ejercicio 5 — Ordenamiento por burbuja manual (avanzado, 30 min)

Enunciado. Implementa el ordenamiento por burbuja (sin pedirle a la IA que te lo dé). Pide 10 números, ordénalos ascendentemente, y muestra el arreglo original y el ordenado paso a paso. Dibuja el diagrama de flujo del algoritmo.

Rúbrica (10 pts): algoritmo correcto (4 pts) + paso a paso (3 pts) + diagrama (2 pts) + formato (1 pt).

Ejercicio 6 — Detección de duplicados (avanzado, 30 min)

Enunciado. Pide 10 números al usuario. Detecta si hay duplicados y, si los hay, muestra cuáles y cuántas veces aparece cada uno. Usa el patrón de doble bucle (for anidado).

Rúbrica (10 pts): doble bucle (4 pts) + detección (3 pts) + conteo (2 pts) + mensajes (1 pt).

Ejercicio bonus — Ordenamiento con swap (opcional, 30 min)

Enunciado. Implementa el ordenamiento por selección: busca el menor de toda la lista, ponlo en la posición 0; luego el segundo menor en la posición 1, etc. Pide 6 números, ordénalos, muestra paso a paso.

Rúbrica bonus (5 pts): algoritmo (3 pts) + paso a paso (1 pt) + verificación (1 pt).

🎯 Cierre del tema

Lo que aprendiste hoy:

  • Qué es un arreglo y por qué es la estructura más usada.
  • Declaración, inicialización y acceso por índice 0-based.
  • Almacenamiento contiguo en memoria y fórmula de direccionamiento.
  • Recorrido con for y las 4 operaciones básicas.
  • Validación de índices y prevención de accesos fuera de rango.
  • 5 algoritmos clásicos: suma, mayor/menor, búsqueda lineal, inversión, duplicados.
  • Comparación con Java y Python.

Lo que sigue: en el Tema 3.2 — Operaciones con Vectores + Análisis de Complejidad O(n) (8h), vas a profundizar en las operaciones más usadas con arreglos: ordenamiento (burbuja, selección, inserción), búsqueda avanzada, y vas a aprender a medir la eficiencia de tus algoritmos con la notación Big O. Esta es la skill que te separa de un junior "que programa" de un mid-level "que programa eficientemente".

Antes de seguir, asegúrate de tener en tu cuaderno:

  • [ ] 6 programas del LAB 3.1 funcionando.
  • [ ] El diagrama de "segmentos de memoria" dibujado a mano con tus palabras.
  • [ ] Los 5 algoritmos clásicos (suma, mayor/menor, búsqueda, inversión, duplicados).
  • [ ] Glosario con: arreglo, índice, contigüidad, O(1), fuera de rango, 0-based, stack, off-by-one.

XP obtenida al completar este tema: 100 base + 30 por LAB (6 ejercicios) + 20 por Quest = 150 XP. Insignia desbloqueada al cerrar el capítulo: Vector Master (parcial).

*"Un programa sin arreglos es una persona con un solo bolsillo. Un programa con arreglos es una persona con un maletín organizado: cada cosa en su lugar, accesible al instante."* — De la introducción de este manual.

Fin del Tema 3.1

📝 Quest · Cuestionario — 📝 Quest — Reactivos para autoevaluación

Las siguientes preguntas te sirven para autoevaluarte después de leer el tema. Responde en tu cuaderno o mentalmente, y luego revisa las Respuestas modelo (disponibles en libre acceso, sin iniciar sesión).

Sección A · Opción múltiple

Elige la opción correcta (A, B, C o D). Las respuestas están en la sección Respuestas modelo.

  1. ¿Cómo se declara un arreglo de 10 enteros en C++?
    • int arr(10);
    • int arr[10];
    • array<int> arr;
    • int arr = 10;
  2. ¿Cuál es el primer índice de un arreglo en C++?
    • 1
    • 0
    • -1
    • Depende
  3. Para acceder al 5to elemento de arr:
    • arr[5]
    • arr[4]
    • arr(5)
    • arr->5
  4. ¿Qué pasa si accedes a arr[10] en un arreglo de tamaño 10?
    • Devuelve 0
    • Comportamiento indefinido (puede crashear)
    • Error de compilación
    • Devuelve null
  5. ¿Cómo se inicializa un arreglo en C++?
    • int arr[5] = {1,2,3,4,5};
    • int arr = [1,2,3,4,5];
    • int arr(5) = 1,2,3;
    • Solo en tiempo de compilación
  6. ¿Qué pasa con elementos no inicializados en un arreglo global?
    • Son null
    • Son 0
    • Son aleatorios
    • Causan error
  7. Un arreglo de 5 doubles ocupa:
    • 5 bytes
    • 40 bytes
    • 20 bytes
    • 10 bytes
  8. ¿Cómo se recorre un arreglo en C++?
    • for (auto x : arr)
    • for (int i=0; i<n; i++)
    • while
    • Todas las anteriores
  9. ¿Cuál es la diferencia entre un arreglo y un vector?
    • Son iguales
    • Vector es dinámico, arreglo es tamaño fijo
    • Vector es más lento siempre
    • Arreglo tiene métodos
  10. ¿Cómo se pasa un arreglo a una función en C++?
    • Por valor (copia completa)
    • Por puntero o por referencia (evita copia)
    • No se puede
    • Por valor es lo único

Sección B · Preguntas abiertas

Desarrolla tu respuesta en al menos 3 líneas. Compara con la respuesta modelo después de escribir.

  1. Diseña una función en pseudocódigo que encuentre el máximo de un arreglo. ¿Complejidad?
    → Escribe tu respuesta aquí (en tu cuaderno o mentalmente)…
  2. Explica la diferencia entre pasar un arreglo por valor y por puntero a una función. ¿Por qué es importante?
    → Escribe tu respuesta aquí (en tu cuaderno o mentalmente)…
  3. ¿Cómo se inicializa un arreglo de 100 elementos con todos en 0? ¿Y uno de 10 elementos con valores específicos?
    → Escribe tu respuesta aquí (en tu cuaderno o mentalmente)…

🟢 Cuando termines, revisa las Respuestas modelo y compáralas con las tuyas. La mejor forma de aprender es discutir cada respuesta contigo mismo o con un compañero.

← Volver a temas del capítulo 📚 Ver todos los temas 🔑 Inicia sesión para hacer el Test