Una sucesión discreta es una lista ordenada de valores indexados por números naturales. Permite describir patrones, estados por paso, costos de algoritmos y datos que evolucionan de manera secuencial.
Una sucesión es una función cuyo dominio suele ser el conjunto de los números naturales. En vez de escribir f(0), f(1), f(2), ... usamos normalmente a0, a1, a2, ... y llamamos término a cada valor de la lista.
Las sucesiones aparecen en programación cada vez que un valor depende de un paso discreto: el saldo después de cada operación, la cantidad de iteraciones de un algoritmo, el tamaño de una estructura, los fotogramas de una simulación o los elementos de un arreglo.
Debemos distinguir el índice del valor. En a5 = 11, el índice es 5 y el término vale 11. En JavaScript, los índices de los arreglos también comienzan normalmente en 0, lo que hace natural esta representación.
Una sucesión no es lo mismo que un conjunto. En una sucesión el orden y las repeticiones importan; en un conjunto, no.
| Objeto | Orden | Repeticiones | Ejemplo |
|---|---|---|---|
| Conjunto | No importa | Se ignoran | {1, 2, 3} |
| Sucesión | Importa | Se permiten | 1, 1, 2, 3, 5, ... |
| Arreglo | Importa | Se permiten | [1, 1, 2, 3, 5] |
Un arreglo es una estructura de datos finita que puede almacenar un tramo de una sucesión. Una sucesión matemática puede ser infinita, mientras que un arreglo concreto ocupa memoria limitada.
Una sucesión está definida explícitamente cuando existe una fórmula que calcula an directamente a partir del índice n. No necesitamos conocer términos anteriores.
function terminoLineal(n) {
return 3 * n + 2;
}
console.log(terminoLineal(0)); // 2
console.log(terminoLineal(5)); // 17Las fórmulas explícitas son cómodas para acceder a un término lejano, porque su cálculo no exige generar los anteriores.
Una sucesión está definida recursivamente cuando especificamos uno o más términos iniciales y una regla para obtener cada término a partir de otros anteriores. Este tema se desarrollará formalmente al estudiar recurrencias.
La definición recursiva describe el proceso de construcción; la definición explícita describe el resultado en función del índice. En este caso ambas definen la misma sucesión: an = 1 + 3n.
Una sucesión aritmética tiene una diferencia constante d entre términos consecutivos. Si el primer término es a0, su fórmula explícita es:
Este patrón modela situaciones que cambian siempre por la misma cantidad, como una cuota fija agregada en cada período o el número de comparaciones de un algoritmo lineal en el peor caso.
function sucesionAritmetica(inicial, diferencia, cantidad) {
const terminos = [];
for (let n = 0; n < cantidad; n++) {
terminos.push(inicial + n * diferencia);
}
return terminos;
}
console.log(sucesionAritmetica(10, 4, 6)); // [10, 14, 18, 22, 26, 30]La variable n cumple el papel de índice. El algoritmo evalúa la fórmula explícita para cada posición solicitada.
Una sucesión geométrica tiene una razón constante r: cada término se obtiene multiplicando el anterior por r. Si a0 es el primer término, la fórmula explícita es an = a0rn.
Las sucesiones geométricas aparecen cuando una cantidad se duplica, se reduce a la mitad o cambia por un porcentaje fijo. También describen la cantidad de nodos de un árbol binario completo por nivel y algunos costos exponenciales.
function sucesionGeometrica(inicial, razon, cantidad) {
const terminos = [];
for (let n = 0; n < cantidad; n++) {
terminos.push(inicial * razon ** n);
}
return terminos;
}
console.log(sucesionGeometrica(3, 2, 6)); // [3, 6, 12, 24, 48, 96]La potencia razon ** n expresa cuántas veces se aplicó el mismo factor de multiplicación.
Algunas sucesiones cambian de fórmula según el índice. Estas definiciones por casos permiten representar condiciones iniciales, alternancias o comportamientos distintos en rangos diferentes.
function sucesionAlternada(n) {
return n % 2 === 0 ? n : -n;
}
console.log([0, 1, 2, 3, 4, 5].map(sucesionAlternada));
// [0, -1, 2, -3, 4, -5]La sucesión de Fibonacci se define con dos términos iniciales y cada término posterior es la suma de los dos anteriores:
No es aritmética porque las diferencias no son constantes, ni geométrica porque las razones tampoco lo son. Es un ejemplo importante de sucesión recursiva de segundo orden.
Una implementación iterativa mantiene solo los dos últimos términos, en lugar de guardar toda la sucesión si no es necesario.
function fibonacciHasta(cantidad) {
const terminos = [];
let anterior = 0;
let actual = 1;
for (let i = 0; i < cantidad; i++) {
terminos.push(anterior);
[anterior, actual] = [actual, anterior + actual];
}
return terminos;
}
console.log(fibonacciHasta(10)); // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]Una sucesión es creciente si cada término es mayor o igual que el anterior; es estrictamente creciente si siempre es mayor. De forma análoga, es decreciente si los términos no aumentan.
| Tipo | Condición | Ejemplo |
|---|---|---|
| Creciente | an+1 ≥ an | 0, 1, 1, 2, 3, ... |
| Estrictamente creciente | an+1 > an | 2, 5, 8, 11, ... |
| Decreciente | an+1 ≤ an | 100, 50, 25, ... |
| Constante | an+1 = an | 7, 7, 7, ... |
Estas propiedades son útiles para demostrar terminación: una cantidad natural no negativa que disminuye estrictamente no puede hacerlo de forma infinita.
Una sucesión está acotada superiormente si existe un número M tal que an ≤ M para todo n. Está acotada inferiormente si existe m tal que m ≤ an para todo n.
En programación, las cotas ayudan a decidir tipos de datos, validar rangos y analizar si una variable puede desbordarse.
El costo de un algoritmo para una entrada de tamaño n puede verse como una sucesión T(n). Por ejemplo, un bucle que realiza n comparaciones produce la sucesión 0, 1, 2, 3, ...; un algoritmo que duplica trabajo en cada nivel puede producir 1, 2, 4, 8, ...
Más adelante estudiaremos notación Big-O para comparar estas sucesiones de costos sin depender de detalles de una implementación concreta.
Un arreglo permite almacenar una cantidad finita de términos y acceder a ellos por índice. Es importante validar que el índice esté dentro del rango disponible.
const cuadrados = [0, 1, 4, 9, 16, 25];
function obtenerTermino(terminos, indice) {
if (!Number.isInteger(indice) || indice < 0 || indice >= terminos.length) {
return "índice fuera de rango";
}
return terminos[indice];
}
console.log(obtenerTermino(cuadrados, 4)); // 16
console.log(obtenerTermino(cuadrados, 8)); // índice fuera de rangoLas sucesiones discretas permiten describir valores que evolucionan según un índice. Al reconocer su fórmula, su regla de construcción y su crecimiento podemos modelar procesos, almacenar datos y analizar algoritmos con mayor precisión.
En el próximo tema estudiaremos las recurrencias, que definen una sucesión a partir de sus términos anteriores.