11. Sucesiones discretas

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.

11.1 Introducción

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.

11.2 Notación básica

Sucesión: (an)n≥0 o simplemente an.

a0: término de índice 0.
an: término de índice n.

Ejemplo: an = 2n + 1.
a0 = 1, a1 = 3, a2 = 5, ...

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.

11.3 Sucesión, conjunto y arreglo

Una sucesión no es lo mismo que un conjunto. En una sucesión el orden y las repeticiones importan; en un conjunto, no.

ObjetoOrdenRepeticionesEjemplo
ConjuntoNo importaSe ignoran{1, 2, 3}
SucesiónImportaSe permiten1, 1, 2, 3, 5, ...
ArregloImportaSe 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.

11.4 Definición explícita

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.

an = 3n + 2

a0 = 2
a1 = 5
a2 = 8
a3 = 11
function terminoLineal(n) {
  return 3 * n + 2;
}

console.log(terminoLineal(0)); // 2
console.log(terminoLineal(5)); // 17

Las fórmulas explícitas son cómodas para acceder a un término lejano, porque su cálculo no exige generar los anteriores.

11.5 Definición recursiva

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.

a0 = 1
an = an-1 + 3, para n ≥ 1.

Sucesión: 1, 4, 7, 10, 13, ...

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.

11.6 Sucesiones aritméticas

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:

an = a0 + nd.

Ejemplo: a0 = 10 y d = 4.
10, 14, 18, 22, 26, ...
an = 10 + 4n.

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.

11.7 Generar una sucesión aritmética

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.

11.8 Sucesiones geométricas

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.

a0 = 3, r = 2.
3, 6, 12, 24, 48, ...

an = 3 · 2n.

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.

11.9 Generar una sucesión geométrica

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.

11.10 Sucesiones definidas por varias reglas

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.

an = n si n es par.
an = -n si n es impar.

Sucesión: 0, -1, 2, -3, 4, -5, ...
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]

11.11 Sucesión de Fibonacci

La sucesión de Fibonacci se define con dos términos iniciales y cada término posterior es la suma de los dos anteriores:

F0 = 0, F1 = 1.
Fn = Fn-1 + Fn-2, para n ≥ 2.

0, 1, 1, 2, 3, 5, 8, 13, ...

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.

11.12 Generar Fibonacci iterativamente

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]

11.13 Sucesiones crecientes, decrecientes y constantes

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.

TipoCondiciónEjemplo
Crecientean+1 ≥ an0, 1, 1, 2, 3, ...
Estrictamente crecientean+1 > an2, 5, 8, 11, ...
Decrecientean+1 ≤ an100, 50, 25, ...
Constantean+1 = an7, 7, 7, ...

Estas propiedades son útiles para demostrar terminación: una cantidad natural no negativa que disminuye estrictamente no puede hacerlo de forma infinita.

11.14 Sucesiones acotadas

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.

an = (-1)n produce 1, -1, 1, -1, ...
Está acotada entre -1 y 1.

an = n no está acotada superiormente.
an = 1 / (n + 1) está acotada entre 0 y 1.

En programación, las cotas ayudan a decidir tipos de datos, validar rangos y analizar si una variable puede desbordarse.

11.15 Sucesiones y complejidad de algoritmos

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, ...

Búsqueda lineal, peor caso: T(n) = n.
Árbol binario completo por nivel: T(n) = 2n.
Búsqueda binaria: cantidad de pasos cercana a log2(n).

Más adelante estudiaremos notación Big-O para comparar estas sucesiones de costos sin depender de detalles de una implementación concreta.

11.16 Representar términos en arreglos

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 rango

11.17 Errores frecuentes

  • Confundir el índice n con el valor an.
  • No indicar si la sucesión comienza en 0 o en 1.
  • Confundir una sucesión con un conjunto y olvidar que el orden importa.
  • Aplicar una fórmula aritmética a una sucesión que no tiene diferencia constante.
  • Usar punto flotante sin considerar la precisión en sucesiones geométricas grandes.
  • Intentar guardar una sucesión infinita completa en memoria.

11.18 Qué debes recordar de este tema

  • Una sucesión es una función indexada normalmente por números naturales.
  • El orden y las repeticiones importan, a diferencia de un conjunto.
  • Puede definirse explícitamente por una fórmula o recursivamente mediante términos anteriores.
  • Las sucesiones aritméticas tienen diferencia constante y las geométricas razón constante.
  • Fibonacci es una sucesión recursiva que depende de dos términos previos.
  • Las sucesiones modelan datos por paso y costos de algoritmos.

11.19 Conclusión

Las 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.