31. Principio de inclusión y exclusión

El principio de inclusión y exclusión permite contar elementos que pertenecen a uno o varios conjuntos sin duplicar los que aparecen en sus zonas de solapamiento. Es una herramienta esencial para consultas, filtros, probabilidades y problemas de conteo.

31.1 Introducción

Contar elementos de varios grupos parece tan simple como sumar sus cantidades. El problema aparece cuando un mismo elemento puede pertenecer a más de un grupo: al sumar, ese elemento se cuenta varias veces.

El principio de inclusión y exclusión corrige ese exceso. Primero incluimos los tamaños de los conjuntos, luego excluimos las intersecciones contadas dos veces y, si hay tres conjuntos, volvemos a incluir la intersección triple.

31.2 Unión e intersección de conjuntos

La unión A ∪ B contiene los elementos que están en A, en B o en ambos. La intersección A ∩ B contiene solamente los elementos que pertenecen simultáneamente a A y a B.

A = {1, 2, 3, 4}.
B = {3, 4, 5}.

A ∪ B = {1, 2, 3, 4, 5}.
A ∩ B = {3, 4}.

La cantidad de elementos de un conjunto finito S se denota |S|. En el ejemplo, |A| = 4, |B| = 3, |A ∩ B| = 2 y |A ∪ B| = 5.

31.3 El problema del doble conteo

Si sumamos |A| + |B| en el ejemplo anterior obtenemos 4 + 3 = 7. Sin embargo, la unión tiene solo 5 elementos porque 3 y 4 se contaron una vez en A y otra vez en B.

|A| + |B| = 7.
Elementos duplicados: |A ∩ B| = 2.

7 - 2 = 5 = |A ∪ B|.

La intersección cuantifica exactamente el exceso. Restarla una vez deja a cada elemento de la unión contado exactamente una vez.

31.4 Fórmula para dos conjuntos

Para dos conjuntos finitos A y B, la fórmula es:

|A ∪ B| = |A| + |B| - |A ∩ B|.

La regla funciona tanto si los conjuntos son disjuntos como si se superponen. Si no comparten elementos, |A ∩ B| = 0 y la fórmula se reduce a una suma ordinaria.

31.5 Demostración mediante clasificación

Separaremos los elementos de A ∪ B en tres clases disjuntas: los que están solo en A, los que están solo en B y los que están en ambos.

Solo A: se cuenta una vez en |A|.
Solo B: se cuenta una vez en |B|.
A ∩ B: se cuenta dos veces al sumar |A| + |B|.

Restar |A ∩ B| deja una única cuenta por elemento.

Esta explicación también muestra por qué no debemos restar una intersección dos veces: los elementos compartidos pasarían a no contarse.

31.6 Ejemplo: criterios de búsqueda

En una colección de documentos, 45 contienen la palabra «algoritmo», 32 contienen «grafo» y 12 contienen ambas. ¿Cuántos contienen al menos una de las dos palabras?

|A ∪ B| = 45 + 32 - 12 = 65.

65 documentos satisfacen «algoritmo OR grafo».

La consulta OR corresponde a la unión. Si una aplicación suma los resultados de dos filtros sin eliminar coincidencias, mostrará duplicados y dará un total incorrecto.

31.7 Operaciones de conjuntos en JavaScript

El tipo Set guarda valores sin repetidos y resulta apropiado para representar conjuntos finitos.

function union(a, b) {
  return new Set([...a, ...b]);
}

function interseccion(a, b) {
  return new Set([...a].filter(valor => b.has(valor)));
}

const a = new Set([1, 2, 3, 4]);
const b = new Set([3, 4, 5]);

console.log([...union(a, b)]);         // [1, 2, 3, 4, 5]
console.log([...interseccion(a, b)]);  // [3, 4]

La cardinalidad de un Set se obtiene con .size. El orden mostrado al convertirlo en arreglo depende del orden de inserción y no forma parte de la definición matemática de conjunto.

31.8 Verificar la fórmula con código

function contarUnionDosConjuntos(a, b) {
  const ambos = interseccion(a, b);
  return a.size + b.size - ambos.size;
}

const usuariosA = new Set(["ana", "bea", "carlos", "diego"]);
const usuariosB = new Set(["carlos", "diego", "elena"]);

console.log(contarUnionDosConjuntos(usuariosA, usuariosB)); // 5
console.log(union(usuariosA, usuariosB).size);              // 5

Comparar la fórmula con la unión construida directamente es una buena manera de probar una implementación. En conjuntos grandes, elegir entre materializar la unión o trabajar solo con cardinalidades depende de los datos disponibles.

31.9 Fórmula para tres conjuntos

Para tres conjuntos A, B y C se suman los tamaños individuales, se restan las intersecciones de pares y se vuelve a sumar la intersección triple:

|A ∪ B ∪ C| = |A| + |B| + |C|
- |A ∩ B| - |A ∩ C| - |B ∩ C|
+ |A ∩ B ∩ C|.

La intersección triple se suma al final porque sus elementos fueron incluidos tres veces y excluidos tres veces; en ese punto todavía tienen conteo cero y deben aparecer una vez.

31.10 Ejemplo con tres conjuntos

En una escuela, 60 estudiantes estudian inglés, 45 estudian francés y 40 estudian programación. Las intersecciones son: 20 estudian inglés y francés, 15 inglés y programación, 10 francés y programación, y 5 estudian las tres áreas.

|A ∪ B ∪ C| = 60 + 45 + 40 - 20 - 15 - 10 + 5.

|A ∪ B ∪ C| = 105.

El valor 105 cuenta a cada estudiante que participa en al menos una de las actividades una sola vez. Las intersecciones de pares incluyen a quienes cursan las tres, por eso la intersección triple debe compensarse.

31.11 Tabla de conteos para tres conjuntos

Un elemento que pertenece a distinta cantidad de conjuntos recibe los siguientes conteos a lo largo de la fórmula:

Ubicación del elementoAl sumar individualesAl restar paresAl sumar tripleTotal
Solo en un conjunto1001
En exactamente dos conjuntos2-101
En los tres conjuntos3-3+11

La tabla es una forma útil de recordar los signos. El objetivo final de la alternancia es que cualquier elemento presente en la unión tenga coeficiente total 1.

31.12 Implementar la unión de varios conjuntos

Si tenemos los elementos explícitos, la forma más simple de contar una unión es insertarlos todos en un único Set. El propio tipo de datos elimina los duplicados.

function unionDeMuchos(conjuntos) {
  const resultado = new Set();
  for (const conjunto of conjuntos) {
    for (const valor of conjunto) resultado.add(valor);
  }
  return resultado;
}

const a = new Set([1, 2, 3]);
const b = new Set([3, 4]);
const c = new Set([2, 4, 5]);

console.log(unionDeMuchos([a, b, c]).size); // 5

El principio de inclusión y exclusión es especialmente útil cuando no tenemos los elementos individuales, sino solo los tamaños de las intersecciones.

31.13 Números divisibles por 2 o por 3

¿Cuántos enteros entre 1 y 100 son divisibles por 2 o por 3? Definimos A como los múltiplos de 2 y B como los múltiplos de 3.

|A| = ⌊100/2⌋ = 50.
|B| = ⌊100/3⌋ = 33.
|A ∩ B| = múltiplos de mcm(2, 3) = 6: ⌊100/6⌋ = 16.

|A ∪ B| = 50 + 33 - 16 = 67.

Los múltiplos de 6 pertenecen a ambos conjuntos; son los que se habían contado dos veces. El máximo común múltiplo conecta este problema con el algoritmo de Euclides.

31.14 Filtrar múltiplos sin duplicados

function multiplosDe2O3(limite) {
  const resultado = [];
  for (let n = 1; n <= limite; n++) {
    if (n % 2 === 0 || n % 3 === 0) resultado.push(n);
  }
  return resultado;
}

const valores = multiplosDe2O3(100);
console.log(valores.length); // 67

La condición OR expresa la unión. Usar dos bucles separados y concatenar resultados requeriría eliminar los múltiplos de 6 repetidos; inclusión y exclusión explica de antemano cuántas repeticiones habría.

31.15 Complemento y elementos que no cumplen condiciones

Si U es un universo finito y queremos contar los elementos que no están en A ∪ B, usamos el complemento:

|U \ (A ∪ B)| = |U| - |A ∪ B|.

Entre 1 y 100, no divisibles por 2 ni por 3:
100 - 67 = 33.

La notación U \ S representa los elementos de U que no pertenecen a S. Contar el complemento suele ser más simple que contar directamente una condición negativa.

31.16 Relación con probabilidad

Si todos los elementos de un universo finito son igualmente probables, al dividir la fórmula por |U| obtenemos la regla de probabilidad para dos eventos:

P(A ∪ B) = P(A) + P(B) - P(A ∩ B).

La fórmula no requiere que A y B sean independientes. La independencia es una condición distinta que afecta cómo se calcula P(A ∩ B), no la validez de inclusión y exclusión.

31.17 Aplicación en bases de datos

Una consulta que combina filtros con OR debe devolver una fila una sola vez, aunque cumpla varias condiciones. En términos de conjuntos, el resultado es la unión de los conjuntos de filas que satisface cada filtro.

Filtro A: usuarios activos.
Filtro B: usuarios con una compra reciente.

A OR B: usuarios activos, compradores recientes o ambos.
La intersección no debe aparecer duplicada en el resultado.

Los motores de bases de datos se ocupan normalmente de la semántica de la consulta, pero conocer la estructura de conjuntos ayuda a razonar sobre totales, índices, deduplicación y rendimiento.

31.18 Forma general

Para n conjuntos finitos, se suman los tamaños de las intersecciones de un conjunto, se restan las de dos conjuntos, se suman las de tres y así sucesivamente, alternando signos.

|A1 ∪ ... ∪ An| =
suma de intersecciones simples
- suma de intersecciones de pares
+ suma de intersecciones de ternas
- ... + (-1)n+1|A1 ∩ ... ∩ An|.

La fórmula puede tener muchas intersecciones: para n conjuntos hay 2n - 1 términos no vacíos. Por eso es muy útil en teoría, pero puede ser costosa si n es grande y se intenta calcular de manera directa.

31.19 Inclusión y exclusión en algoritmos

La técnica aparece al contar cadenas que evitan patrones, números que cumplen restricciones, asignaciones sin conflictos y soluciones que satisfacen al menos una condición. También sirve para estimar resultados de filtros que se solapan.

En programación práctica, si se dispone de todos los elementos suele ser más sencillo usar un Set. La fórmula cobra valor cuando los conjuntos son demasiado grandes, están definidos implícitamente o solo se conocen sus cardinalidades e intersecciones.

31.20 Estrategia para resolver problemas

  1. Define el universo y cada conjunto que representa una condición.
  2. Decide si buscas la unión, una intersección o un complemento.
  3. Cuenta los conjuntos individuales.
  4. Cuenta las intersecciones necesarias.
  5. Aplica signos alternados y verifica que cada elemento quede contado una vez.

Un diagrama de Venn puede ayudar con dos o tres conjuntos. Para más conjuntos, las fórmulas y una tabla de signos suelen ser más claras que intentar dibujar todas las regiones.

31.21 Errores frecuentes

  • Sumar tamaños de conjuntos sin descontar los elementos compartidos.
  • Restar la intersección triple en vez de volver a sumarla.
  • Usar una intersección de pares que excluye erróneamente a la intersección triple.
  • Confundir OR con AND al traducir una consulta o condición.
  • Calcular múltiplos comunes con el producto en lugar de usar el mcm.
  • Asumir independencia de eventos sin que el problema lo establezca.

31.22 Qué debes recordar y conclusión

  • La unión representa elementos que cumplen al menos una condición.
  • Para dos conjuntos: |A ∪ B| = |A| + |B| - |A ∩ B|.
  • Para tres conjuntos se restan las intersecciones de pares y se suma la triple.
  • La alternancia de signos evita contar un elemento más de una vez.
  • La fórmula se aplica a conteo, filtros, bases de datos, divisibilidad y probabilidad.
  • Un Set es útil para materializar una unión concreta sin duplicados.

El principio de inclusión y exclusión convierte solapamientos complejos en una suma controlada de intersecciones. En el próximo tema estudiaremos relaciones de equivalencia y de orden, que permiten describir cómo se vinculan formalmente los elementos de un conjunto.