Atlasingeniería

Algoritmos y programaciónFundamentosTema 3

Condicionales y ciclos que terminan

El control de flujo decide qué instrucciones se ejecutan y cuántas veces. Diseñarlo bien exige condiciones completas, progreso visible y una salida alcanzable.

Para este tema conviene tener claro:Variables, tipos y expresiones

Un programa deja de ser una lista fija cuando puede elegir y repetir. Esas dos capacidades resuelven problemas, pero también crean ramas olvidadas y ciclos infinitos. La clave es hacer explícitas las condiciones.

Las ramas tienen que ser casos del dominio

Un condicional selecciona una ruta según una expresión booleana. Las ramas deberían representar casos del dominio, no combinaciones accidentales de flags.

Ordenar condiciones importa: una rama general colocada primero puede volver inalcanzable una más específica. Para rangos, conviene revisar fronteras exactas y preguntar dónde caen igualdad, valores mínimos y entradas inválidas.

Antes de seguir, predecí

Un ciclo que recorre una lista y borra elementos mientras recorre. ¿Qué pasa?

Cuándo for y cuándo while

Un for resulta claro cuando conocemos inicialización, condición y avance. Un while expresa mejor una repetición cuya cantidad depende del estado:

let index = 0;
while (index < values.length && values[index] !== target) {
  index += 1;
}

El estado observado por la condición debe cambiar dentro del ciclo; de lo contrario, una condición verdadera puede permanecer verdadera para siempre.

Buscamos el 5. El índice arranca en 0 y la condición mira dos cosas: que quede arreglo y que no sea el buscado.

1 / 5
El índice avanza y está acotado por la longitud: esas dos cosas juntas son las que garantizan que el ciclo termina. Si alguna de las dos falta, se cuelga.

Una medida que se acerca a un límite

Para justificar que termina, elegimos una medida que se acerca a un límite. En el ejemplo, index aumenta y está acotado por la longitud. Quedan cada vez menos posiciones posibles.

Un break puede ser correcto, pero no debería ocultar que ninguna ruta garantiza progreso. Una salida temprana es más clara cuando expresa directamente que el objetivo ya fue alcanzado o que continuar no puede cambiar la respuesta.

Anidado no siempre es cuadrático

Los ciclos anidados no siempre implican costo cuadrático. Si ambos recorren toda la entrada, hacen n2n^2 iteraciones. Si dos índices avanzan sin retroceder sobre la misma colección, el trabajo total puede seguir siendo lineal.

Contar cuánto cambia cada índice es más confiable que contar llaves o niveles visuales. El flujo determina el costo, no la indentación por sí sola.

El mismo recorrido, de cuatro formas

const orders = [
  { id: 'a', total: 1200, paid: true },
  { id: 'b', total: 800, paid: false },
  { id: 'c', total: 3000, paid: true },
];

// 1. Con índice: el más flexible y el que más se puede equivocar
let total = 0;
for (let index = 0; index < orders.length; index += 1) {
  if (orders[index]!.paid) total += orders[index]!.total;
}

// 2. Con for..of: sin índice, no hay borde que errar
let total2 = 0;
for (const order of orders) {
  if (!order.paid) continue; // salida temprana: el caso normal queda sin sangría
  total2 += order.total;
}

// 3. Declarativo: dice qué, no cómo
const total3 = orders.filter((order) => order.paid).reduce((sum, order) => sum + order.total, 0);

// 4. Con corte temprano, que las tres anteriores no tienen
const firstBig = orders.find((order) => order.total > 1000);

Las tres primeras dan lo mismo y se leen distinto. La del índice es la única que hace falta cuando hay que mirar dos posiciones a la vez o recorrer al revés; para todo lo demás, el índice es una variable de más que puede estar mal.

Cómo se leen las condiciones

En vez deEscribirPor qué
if (!noEsValido)if (esValido)una negación menos que traducir en cada lectura
if (a) { ... } else { }if (!a) { ... }una rama vacía es ruido
Condiciones anidadas de tres nivelessalidas tempranasel caso normal queda al final, sin sangría
if con cinco comparacionesuna constante o función con nombreel nombre dice qué significa la condición
while con contador a manofor..of o mapel índice deja de poder equivocarse
Las cinco filas son el mismo consejo: el código lo escribe una persona y lo leen veinte, y la condición es donde más cuesta leer.

Lo que preguntan sobre esto

Cierre

Los condicionales deben cubrir casos sin esconder ramas; los ciclos deben mostrar progreso y una salida alcanzable. Cuando podés nombrar el estado, la condición y la medida que avanza, el control de flujo deja de ser ensayo y error.

Autoevaluación

¿Lo entendiste?

Una rama general está escrita antes que una más específica. ¿Qué pasa?
¿Qué garantiza que un while termine?
Dos ciclos anidados, ¿siempre son O(n²)?
Al escribir un condicional sobre rangos, ¿qué hay que revisar sí o sí?