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.
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.
La matemática discreta reúne varias áreas que comparten el estudio de estructuras separadas. Cada una responde preguntas muy habituales al programar.
| Área | Pregunta que responde | Ejemplo 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 |
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.
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.
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ón | Modelo continuo | Modelo discreto usado por el programa |
|---|---|---|
| Tiempo | Una magnitud real | Milisegundos o marcas de tiempo |
| Imagen | Una escena visual | Matriz finita de píxeles |
| Sonido | Onda continua | Muestras tomadas por segundo |
| Ubicación | Punto del plano | Coordenadas 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.
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.
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.
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.
| Problema | Modelo discreto | Operación principal |
|---|---|---|
| Seguidores en una red social | Grafo dirigido | Recorrer conexiones |
| Carpetas de un proyecto | Árbol | Buscar o recorrer nodos |
| Roles y permisos | Conjuntos y relaciones | Comprobar pertenencia |
| Contraseña segura | Combinatoria | Contar posibilidades |
| Validación de un correo | Lenguaje formal | Reconocer 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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.