1. ¿Qué es la matemática discreta y por qué es importante en programación?

La matemática discreta estudia estructuras formadas por elementos separados y contables. Es el lenguaje que permite especificar, diseñar, demostrar y analizar algoritmos, programas, redes, bases de datos y sistemas de seguridad.

1.1 Introducción

Un programa trabaja con datos que pueden representarse, almacenarse y procesarse: caracteres, números enteros, registros, nodos de una red, estados de una aplicación o instrucciones. La matemática discreta ofrece modelos para describir esos objetos y reglas para razonar con precisión sobre ellos.

El término discreta no significa sencilla ni secundaria. Indica que sus objetos se presentan como unidades distinguibles: podemos enumerarlos, compararlos, conectarlos o agruparlos. Una contraseña tiene una cantidad finita de caracteres posibles; un grafo tiene vértices y aristas; un algoritmo ejecuta una sucesión de pasos; una tabla de una base de datos contiene registros.

En este curso relacionaremos cada concepto con problemas de programación y ejemplos en JavaScript. La meta es aprender a pensar con rigor: no solo obtener un resultado, sino explicar por qué un algoritmo funciona, cuánto cuesta y en qué casos puede fallar.

1.2 ¿Qué estudia la matemática discreta?

La matemática discreta reúne varias áreas que comparten el estudio de estructuras separadas. Cada una responde preguntas muy habituales al programar.

ÁreaPregunta que respondeEjemplo en programación
Lógica y demostraciones¿La conclusión se deduce de las condiciones?Verificar precondiciones e invariantes
Conjuntos, relaciones y funciones¿Cómo se vinculan los datos?Modelar usuarios, permisos y claves
Conteo y combinatoria¿Cuántas posibilidades existen?Calcular espacio de claves o casos de prueba
Recurrencias y complejidad¿Cómo crece el trabajo de un algoritmo?Analizar búsquedas y ordenamientos
Aritmética modular¿Cómo operar con restos?Criptografía, hashes y calendarios
Álgebra de Boole¿Cómo combinar valores verdadero y falso?Condiciones, consultas y circuitos
Grafos y árboles¿Qué elementos están conectados?Rutas, redes sociales y dependencias
Autómatas y lenguajes formales¿Qué cadenas son válidas?Analizadores léxicos y expresiones regulares

1.3 Objetos discretos: elementos separados

Un objeto es discreto cuando sus valores aparecen como unidades separadas. Entre dos valores consecutivos puede no existir otro valor válido dentro del modelo. Por ejemplo, un arreglo de JavaScript tiene posiciones numeradas: después del índice 4 viene el índice 5; no existe un elemento en el índice 4,5.

Ejemplos de objetos discretos:
• Los caracteres de un texto: A, B, C, ...
• Los números naturales: 0, 1, 2, 3, ...
• Los estados de un semáforo o de una interfaz
• Los vértices y aristas de una red
• Las filas de una tabla de base de datos

Que un conjunto sea muy grande no lo vuelve continuo. El conjunto de todas las cadenas de longitud 20 puede ser enorme, pero cada cadena es una secuencia finita de símbolos y puede tratarse mediante reglas discretas.

1.4 Discreto y continuo

La matemática continua suele modelar magnitudes que pueden tomar cualquier valor dentro de un intervalo, como el tiempo físico, la temperatura o una distancia idealizada. Allí son centrales las funciones reales, los límites, las derivadas y las integrales.

La informática puede recibir datos continuos desde el mundo real, pero para procesarlos necesita representarlos con una cantidad finita de bits. Una fotografía digital no contiene infinitos colores: guarda valores numéricos en una grilla de píxeles. Una medición de temperatura se almacena con cierta precisión limitada.

SituaciónModelo continuoModelo discreto usado por el programa
TiempoUna magnitud realMilisegundos o marcas de tiempo
ImagenUna escena visualMatriz finita de píxeles
SonidoOnda continuaMuestras tomadas por segundo
UbicaciónPunto del planoCoordenadas con precisión finita

Ambas ramas son valiosas. La matemática discreta domina cuando interesan estructuras, decisiones y pasos finitos; la continua es esencial cuando el problema exige modelar cambios sin saltos.

1.5 La computadora es una máquina discreta

En el nivel lógico, una computadora procesa símbolos y estados finitos. La memoria se organiza en posiciones, los datos se codifican mediante bits y las instrucciones se ejecutan como una secuencia. Aunque el hardware usa fenómenos físicos continuos, el diseño de los programas se expresa con abstracciones discretas.

Bit: 0 o 1
Byte: secuencia de 8 bits
Booleano: true o false
Índice de un arreglo: 0, 1, 2, ...
Estado de un programa: una configuración definida de variables y control

Esta observación explica por qué los conceptos discretos son tan cercanos a la programación. Un if toma una decisión booleana; un for recorre una sucesión de índices; una función recursiva se analiza mediante una recurrencia; un compilador reconoce cadenas mediante reglas formales.

1.6 Del enunciado al modelo matemático

Resolver un problema informático exige transformar una situación real en una estructura que el programa pueda manipular. La matemática discreta ayuda a elegir esa estructura y a identificar las propiedades que deben conservarse.

ProblemaModelo discretoOperación principal
Seguidores en una red socialGrafo dirigidoRecorrer conexiones
Carpetas de un proyectoÁrbolBuscar o recorrer nodos
Roles y permisosConjuntos y relacionesComprobar pertenencia
Contraseña seguraCombinatoriaContar posibilidades
Validación de un correoLenguaje formalReconocer patrones

El modelo no es el programa terminado. Es una representación simplificada que permite razonar antes de escribir código. Elegir bien el modelo suele ser la parte más importante de la solución.

1.7 Algoritmos: procedimientos finitos y precisos

Un algoritmo es un procedimiento formado por pasos bien definidos que transforma una entrada en una salida. Para que sea útil debe indicar qué hacer en cada situación relevante y debe terminar cuando la tarea lo requiera.

Por ejemplo, encontrar el mayor número de un arreglo parece una tarea simple, pero ilustra una idea esencial: recorrer elementos discretos manteniendo una propiedad verdadera durante todo el proceso.

function buscarMaximo(numeros) {
  if (numeros.length === 0) {
    throw new Error("Se necesita al menos un número");
  }

  let maximo = numeros[0];

  for (let i = 1; i < numeros.length; i++) {
    if (numeros[i] > maximo) {
      maximo = numeros[i];
    }
  }

  return maximo;
}

console.log(buscarMaximo([8, 3, 12, 5, 9])); // 12

La idea matemática detrás del código es el invariante: después de examinar los elementos desde la posición 0 hasta la posición i, la variable maximo guarda el mayor de esos elementos. Más adelante usaremos demostraciones para justificar afirmaciones de este tipo.

1.8 Corrección: ¿por qué un algoritmo funciona?

Que un programa produzca una salida en algunos ejemplos no demuestra que sea correcto. Para afirmar que un algoritmo resuelve un problema, debemos establecer qué recibe, qué debe devolver y por qué sus pasos garantizan ese resultado para todas las entradas válidas.

Especificación de buscarMaximo:

Precondición: numeros es un arreglo no vacío de números.
Postcondición: devuelve un valor del arreglo que es mayor o igual que todos los demás.

Las pruebas automáticas buscan contraejemplos y son indispensables en el desarrollo. Una demostración matemática complementa esas pruebas: ofrece una garantía general que no depende de haber elegido muchos casos de ejemplo. En los próximos temas veremos demostración directa, contraposición, contradicción e inducción.

1.9 Eficiencia: no basta con que funcione

Dos algoritmos pueden resolver el mismo problema y requerir cantidades muy diferentes de tiempo o memoria. La matemática discreta permite contar operaciones y describir cómo crece el costo cuando aumenta el tamaño de la entrada.

Para buscar un elemento en una lista no ordenada, en el peor caso debemos revisar todos los elementos. Si la lista tiene n elementos, la cantidad de comparaciones es como máximo n. Se dice que el algoritmo tiene crecimiento lineal.

function contiene(numeros, buscado) {
  for (const numero of numeros) {
    if (numero === buscado) return true;
  }

  return false;
}

const valores = [4, 8, 15, 16, 23, 42];

console.log(contiene(valores, 16)); // true
console.log(contiene(valores, 10)); // false

En cambio, si el arreglo está ordenado, la búsqueda binaria descarta aproximadamente la mitad de los candidatos en cada paso. Esta diferencia entre revisar uno por uno y dividir repetidamente el problema será central al estudiar notación Big-O.

1.10 Conteo: medir posibilidades y recursos

Contar es más que obtener un número. En programación permite estimar recursos, diseñar pruebas y evaluar seguridad. Si una clave usa 10 símbolos posibles y tiene longitud 4, existen 10 × 10 × 10 × 10 = 104 claves posibles, si se permite repetir símbolos.

Un PIN de cuatro dígitos usa los símbolos 0 a 9.
Cantidad de PIN posibles = 104 = 10 000.

Si no se permite repetir dígitos: 10 × 9 × 8 × 7 = 5 040.

La diferencia importa: una regla aparentemente pequeña cambia el tamaño del espacio de búsqueda. El principio del palomar y el principio de inclusión y exclusión, que veremos más adelante, permiten resolver problemas de conteo más complejos.

1.11 Lógica booleana y decisiones

Los programas toman decisiones con expresiones que solo pueden ser verdaderas o falsas. La lógica booleana estudia cómo se combinan estas condiciones mediante operadores como AND, OR y NOT.

const tieneUsuarioActivo = true;
const esAdministrador = false;
const tienePermisoDeEdicion = true;

const puedeEditar = tieneUsuarioActivo &&
  (esAdministrador || tienePermisoDeEdicion);

console.log(puedeEditar); // true

La expresión anterior no es solo sintaxis. Afirma que una persona puede editar cuando está autenticada y, además, es administradora o posee permiso de edición. Las tablas de verdad y el álgebra de Boole permiten verificar, simplificar y diseñar este tipo de reglas.

1.12 Grafos: modelar conexiones

Un grafo está formado por vértices y aristas. Los vértices representan entidades y las aristas representan relaciones o conexiones. Este modelo aparece siempre que interesa saber quién se conecta con quién o cómo llegar de un punto a otro.

Vértices: A, B, C, D
Aristas: A-B, A-C, B-D, C-D

Interpretación: cuatro ciudades y las rutas directas entre ellas.

Con grafos podemos buscar el camino más corto en un mapa, encontrar dependencias entre tareas, recomendar contactos en una red social o analizar enlaces de una página web. Los árboles son un tipo especial de grafo que se utiliza para representar jerarquías, como directorios y estructuras de búsqueda.

1.13 Aritmética modular y seguridad

La aritmética modular trabaja con los restos de las divisiones. Por ejemplo, 17 y 5 dejan el mismo resto al dividirse por 12; por eso se escribe 17 ≡ 5 (mod 12). Es la matemática del reloj: después de las 11 vienen las 0 o las 12, según la convención utilizada.

function esPar(numero) {
  return numero % 2 === 0;
}

function siguienteHora(hora) {
  return (hora + 1) % 24;
}

console.log(esPar(18));       // true
console.log(siguienteHora(23)); // 0

Además de calendarios y ciclos, las congruencias son fundamentales en criptografía. Operaciones con números grandes y propiedades de divisibilidad permiten crear mecanismos para cifrar, firmar y verificar información.

1.14 Relaciones, bases de datos y estructuras

Una relación indica qué pares de elementos están vinculados. Por ejemplo, la relación «un usuario sigue a otro usuario» relaciona pares de cuentas. Algunas relaciones tienen propiedades importantes: pueden ser reflexivas, simétricas, transitivas o de orden.

En una base de datos relacional, una tabla también representa una relación en otro sentido: una colección de tuplas o filas con atributos definidos. Las claves primarias, las claves foráneas y las restricciones de integridad se apoyan en ideas de conjuntos, funciones y relaciones.

Usuarios(id, nombre)
Sigue(idSeguidor, idSeguido)

Cada fila de Sigue representa una relación entre dos usuarios.

1.15 Lenguajes formales y validación

Un lenguaje formal es un conjunto de cadenas construidas con un alfabeto y sujetas a reglas. Un identificador válido, una dirección de correo o la sintaxis de un lenguaje de programación pueden estudiarse de esta manera.

Las expresiones regulares son una herramienta práctica para reconocer patrones. No sustituyen una validación completa en todos los contextos, pero muestran cómo una definición formal se convierte en una herramienta de programación.

const patronIdentificador = /^[A-Za-z_][A-Za-z0-9_]*$/;

console.log(patronIdentificador.test("total_2026")); // true
console.log(patronIdentificador.test("2total"));     // false

La expresión exige una letra o guion bajo al inicio y luego permite letras, dígitos o guiones bajos. Más adelante estudiaremos autómatas, gramáticas y expresiones regulares con una base más formal.

1.16 Del razonamiento matemático al código

La matemática discreta y la programación se complementan constantemente. Una definición precisa inspira una implementación; una implementación obliga a considerar casos límite; una demostración explica la corrección; un análisis de complejidad ayuda a elegir entre alternativas.

  1. Definir con claridad el problema, las entradas y las salidas.
  2. Elegir una estructura discreta que represente la situación.
  3. Diseñar un algoritmo con pasos finitos y verificables.
  4. Probar su corrección para toda entrada válida.
  5. Analizar tiempo y memoria antes de usarlo con datos grandes.

Esta forma de trabajar evita depender solo de la intuición. También facilita comunicar soluciones a otras personas, revisar código y mantener sistemas complejos.

1.17 Cómo se organiza este curso

Comenzaremos con las herramientas de razonamiento que permiten justificar resultados. Luego estudiaremos sucesiones, recurrencias y complejidad; después trabajaremos con aritmética modular, conteo, relaciones y lógica; finalmente abordaremos grafos, autómatas y aplicaciones.

  • Demostraciones: aprenderemos a justificar afirmaciones mediante métodos rigurosos.
  • Recurrencias y complejidad: analizaremos algoritmos iterativos y recursivos.
  • Conteo y modularidad: resolveremos problemas de posibilidades, divisibilidad y criptografía.
  • Lógica y relaciones: modelaremos decisiones, datos y estructuras.
  • Grafos y lenguajes: estudiaremos redes, árboles, autómatas y gramáticas.

1.18 Errores frecuentes

  • Creer que la matemática discreta consiste únicamente en trabajar con números enteros.
  • Suponer que probar algunos ejemplos garantiza que un algoritmo es correcto.
  • Elegir una estructura de datos sin antes modelar las relaciones del problema.
  • Confundir que un algoritmo sea correcto con que sea eficiente.
  • Usar expresiones booleanas complejas sin analizar sus condiciones y casos límite.
  • Pensar que los temas de grafos, criptografía o bases de datos no están relacionados entre sí.

1.19 Qué debes recordar de este tema

  • La matemática discreta estudia objetos separados, finitos o contables, y las relaciones entre ellos.
  • Es esencial para modelar datos, diseñar algoritmos y demostrar que una solución es correcta.
  • La programación utiliza estructuras discretas: bits, estados, índices, cadenas, árboles y grafos.
  • La corrección y la eficiencia son propiedades distintas que deben analizarse.
  • La lógica, el conteo, las recurrencias, la modularidad, los grafos y los lenguajes formales tienen aplicaciones directas en software.
  • Modelar primero el problema permite elegir mejores estructuras y algoritmos.

1.20 Conclusión

La matemática discreta proporciona el vocabulario y las herramientas para transformar problemas de programación en estructuras que pueden analizarse con precisión. Gracias a ella podemos razonar sobre decisiones, conexiones, conteos, algoritmos y seguridad.

En el próximo tema recorreremos la historia de esta disciplina y veremos cómo sus ideas se convirtieron en fundamentos de la informática moderna.