Cálculo iterativo masivo: REDUCE + APILARV vs BISECCIÓN recursiva vs cálculo directo

Nuevo caso que combina logística portuaria con fórmulas avanzadas de Excel. Un miembro necesita calcular la distribución de días de almacenaje y tonelaje por buque en un puerto, procesando más de 26.000 filas de operaciones de carga (graneles sólidos, líquidos, carga general). Cada buque requiere cruzar datos de recaladas, fechas de llegada y maniobras, lo que genera dependencias entre filas.

El fichero adjunto contiene tres bloques paralelos de análisis (Granel Sólido, Granel Sólido Granos, Granel Sólido Harinas) con la misma lógica implementada de dos formas distintas para comparar rendimiento:

La solución intuitiva usa REDUCE + APILARV (iteración secuencial): REDUCE itera buque a buque y APILARV va apilando los resultados. Dentro de cada iteración se cruzan datos con BUSCARX, se filtran con FILTRAR y se agrupan con AGRUPARPOR. Funciona, pero es lenta porque cada paso acumula la matriz completa y realiza cálculos internos costosos.

El segundo enfoque usa una LAMBDA recursiva con bisección (divide and conquer). En lugar de procesar los buques uno a uno, parte la lista en dos mitades, procesa cada mitad por separado y combina con APILARV:

``
=LET(
...
F; LAMBDA(F; v;
LET(
n; FILAS(v);
SI(n = 1;
[procesar un solo buque];
APILARV(
F(F; TOMAR(v; n/2));
F(F; EXCLUIR(v; n/2))
)
)
)
);
F(F; lista_buques)
)
`

La bisección evita el problema de stack overflow que REDUCE sufre con muchas iteraciones, y el procesamiento "divide y vencerás" es más eficiente para matrices grandes.

John analiza el modelo a fondo y descubre un tercer enfoque: cálculo directo (sin iteración). Gran parte de los cálculos iterativos eran en realidad independientes entre buques: se podían resolver con AGRUPARPOR, BUSCARX y operaciones matriciales directas sin necesidad de iterar. Su versión reestructurada resulta ser la más rápida con diferencia.

La reflexión clave de Leo: "Siempre que se pueda, es mejor hacer cálculos directos que usar recursiones o iteraciones. El problema no era tanto la forma de iterar (REDUCE o bisección) sino todos los cálculos innecesarios dentro del bucle."

Como bonus, el fichero incluye un ajuste de distribución Gamma (GAMMA.DIST`) sobre los datos de permanencia, calculando media ponderada, varianza y parámetros alpha/beta para modelizar estadísticamente el comportamiento del almacenaje.

Un caso fascinante que mezcla logística real, funciones avanzadas y una lección de rendimiento: antes de optimizar el cómo se itera, merece la pena cuestionar si realmente necesitas iterar.

El problema: 26.000 filas de operaciones portuarias

Este caso mezcla logística portuaria real con fórmulas avanzadas. Un miembro de la comunidad necesita calcular la distribución de días de almacenaje y tonelaje por buque en un puerto, procesando más de 26.000 filas de operaciones de carga (graneles sólidos, líquidos y carga general). Cada buque obliga a cruzar recaladas, fechas de llegada y maniobras, lo que genera dependencias entre filas. El fichero implementa la misma lógica de dos formas distintas para comparar rendimiento, y de ahí sale una de las mejores lecciones de optimización que ha dado la comunidad.

Enfoque 1: REDUCE + APILARV (iteración secuencial)

La solución intuitiva usa REDUCE para iterar buque a buque y APILARV para ir apilando los resultados. Dentro de cada iteración se cruzan datos con BUSCARX, se filtran con FILTRAR y se agrupan con AGRUPARPOR:

`` =REDUCE(cabecera; lista_buques; LAMBDA(acumulado; buque; APILARV(acumulado; procesar(buque)) )) ``

Funciona, pero es lenta: en cada paso el acumulador arrastra la matriz completa calculada hasta ese momento, y encima repite cálculos internos costosos en cada vuelta.

Enfoque 2: LAMBDA recursiva con bisección

El segundo enfoque cambia la estrategia por un "divide y vencerás". En lugar de procesar los buques uno a uno, parte la lista en dos mitades, procesa cada mitad por separado y las combina con APILARV:

`` =LET( F; LAMBDA(F; v; LET( n; FILAS(v); SI(n = 1; procesar_un_buque(v); APILARV( F(F; TOMAR(v; n/2)); F(F; EXCLUIR(v; n/2)) ) ) ) ); F(F; lista_buques) ) ``

El patrón clave es F(F; TOMAR(v; n/2)) y F(F; EXCLUIR(v; n/2)): la LAMBDA se llama a sí misma con cada mitad. La bisección evita el desbordamiento de pila que sufre REDUCE con muchas iteraciones y suele ir más rápida en matrices grandes. La comunidad bautizó la técnica como el "Biseccionator".

Enfoque 3: cálculo directo (la gran lección)

John analiza el modelo a fondo y descubre algo revelador: buena parte de los cálculos no eran realmente iterativos. Muchos resultados eran independientes entre buques y se podían resolver con AGRUPARPOR, BUSCARX y operaciones matriciales directas, sin iterar en absoluto. Su versión reestructurada resulta ser, con diferencia, la más rápida.

La reflexión de Leo lo resume perfecto: lo importante no era tanto cómo iterar (REDUCE o bisección), sino todos los cálculos innecesarios que se metían dentro del bucle. Antes de optimizar el cómo iteras, pregúntate si de verdad necesitas iterar.

Bonus estadístico

El fichero incluye además un ajuste de distribución Gamma con GAMMA.DIST sobre los datos de permanencia, calculando media ponderada, varianza y los parámetros alpha y beta para modelizar el comportamiento del almacenaje. Un recordatorio de que Excel también sirve para modelado estadístico serio.

Funciones clave

  • REDUCE + APILARV: el patrón clásico de iteración acumulativa; cómodo pero costoso cuando el acumulador crece mucho.
  • LAMBDA recursiva: permite implementar bisección llamando a la función sobre cada mitad del array.
  • TOMAR y EXCLUIR: parten el rango en dos para el "divide y vencerás".
  • AGRUPARPOR y BUSCARX: la base del cálculo directo, que resuelve sin iterar lo que parecía necesitar un bucle.
  • GAMMA.DIST: modelado estadístico de la permanencia de la carga.

Conclusión

Tres formas de atacar el mismo modelo, y un orden de rendimiento claro: la iteración secuencial es la más lenta, la bisección la mejora, pero el cálculo directo las supera a todas porque elimina el trabajo innecesario en lugar de hacerlo más rápido. La moraleja va más allá de este caso: la mejor optimización no es acelerar el bucle, sino descubrir que no lo necesitabas. Casos así, con problemas reales y varias mentes buscándoles la vuelta, son el día a día de la comunidad de Influexcel.

Más contenido de Excel en InflueXcel