Qué es un algoritmo y qué es un programa

Enterate del próximo post
Un mail cuando publico algo nuevo. Sin spam y te podés dar de baja cuando quieras.

Un mail cuando publico algo nuevo. Sin spam y te podés dar de baja cuando quieras.
En el reverso de un paquete de fideos hay una lista de pasos: poner a hervir dos litros de agua, agregar sal, sumergir los fideos, esperar diez minutos, colar. Esa lista no es la cena, y tampoco depende de la cocina donde se ejecute: sirve igual sobre una hornalla a gas, sobre una eléctrica o sobre un fuego a leña. Los pasos son los mismos; lo que cambia es quién los ejecuta y con qué herramientas.
Programar funciona igual, y buena parte de la dificultad de quien recién empieza viene de mezclar esas dos cosas: la lista de pasos y la cocina donde se ejecutan. Este es el primer post de una serie sobre fundamentos de la programación, y arranca justamente por esa separación, porque todo lo que viene después se apoya en ella.
Hay tres cosas distintas en juego, y conviene nombrarlas por separado desde el principio.
El problema es lo que se quiere resolver, enunciado sin decir cómo: "convertir una temperatura de grados Celsius a Fahrenheit". Un problema no tiene pasos, tiene un punto de partida y un resultado deseado.
El algoritmo es la secuencia de pasos que resuelve ese problema. Es la solución en sí, expresada de forma que cualquiera pueda seguirla: una persona con lápiz y papel, o una computadora.
El programa es ese algoritmo escrito en un lenguaje que una computadora puede ejecutar. Es una traducción, no una solución nueva.
No cualquier lista de pasos es un algoritmo. Hacen falta tres condiciones:
La distinción importa por una razón práctica. El error más caro que se puede cometer al programar no es escribir mal una línea de código: el compilador o el intérprete avisan de eso en el momento. El error caro es escribir perfectamente un algoritmo que no resuelve el problema, o que ni siquiera llegó a pensarse antes de empezar a teclear. Ese error no lo detecta ninguna herramienta, y no se arregla cambiando de lenguaje: un algoritmo mal pensado sigue estando mal pensado traducido a otro idioma.
Para hablar de algoritmos sin quedar atados a ningún lenguaje, esta serie usa una notación propia. No es código real, no compila en ningún lado, y eso es a propósito: obliga a mirar los pasos y no la sintaxis.
Las reglas son pocas. El nombre del algoritmo va en la primera línea, terminado en dos puntos. Cada paso ocupa una línea, escrito como una instrucción, e indentado debajo del nombre. Si el algoritmo produce un resultado, la última línea lo devuelve.
algoritmo hervir_fideos:
poner dos litros de agua en una olla
calentar el agua hasta que hierva
agregar una cucharada de sal
sumergir los fideos
esperar diez minutos
colar los fideosEse algoritmo cumple las tres condiciones: termina, cada paso significa una sola cosa, y el resultado es claro aunque no se devuelva nada explícito. No todos los algoritmos devuelven un valor; los de la cocina, por ejemplo, dejan su resultado en la olla.
El segundo ejemplo sí devuelve algo, y recibe un dato para trabajar. Ese dato va entre paréntesis, al lado del nombre.
algoritmo celsius_a_fahrenheit(grados_celsius):
multiplicar grados_celsius por 9/5
sumar 32 al resultado
devolver el resultadoEste es el punto exacto donde se ve la diferencia entre algoritmo y programa. Ese mismo algoritmo, escrito en JavaScript:
function celsiusAFahrenheit(gradosCelsius) {
return gradosCelsius * 9 / 5 + 32;
}
console.log(celsiusAFahrenheit(100));
// 212Y escrito en Python:
def celsius_a_fahrenheit(grados_celsius):
return grados_celsius * 9 / 5 + 32
print(celsius_a_fahrenheit(100))
# 212.0Los dos programas se ven distintos. Uno declara la función con function y el otro con def, uno usa llaves y el otro indentación, uno imprime con console.log y el otro con print. Hasta el resultado se muestra distinto: JavaScript imprime 212 y Python imprime 212.0, porque cada lenguaje decide por su cuenta cómo representar los números.
Nada de eso es el algoritmo. El algoritmo es uno solo, y es el mismo en los dos: multiplicar, sumar, devolver. Todo lo demás son convenciones del idioma en el que se lo escribió. Por eso alguien que aprendió a pensar algoritmos puede leer código de un lenguaje que nunca usó y entender qué hace, aunque no sepa escribirlo.
Un producto tiene un precio sin impuesto y le corresponde un porcentaje de impuesto. Escribir el algoritmo que calcula el precio final.
Todavía no hace falta ninguna decisión ni ninguna repetición: son pasos en orden, uno detrás del otro, como los dos ejemplos anteriores.
Pista: conviene arrancar por el final. Antes de escribir el primer paso, responder dos preguntas: qué datos hacen falta para empezar (van entre paréntesis) y qué valor tiene que quedar en la línea del devolver. Los pasos del medio son los que conectan una cosa con la otra.
algoritmo precio_final(precio, porcentaje_impuesto):
dividir porcentaje_impuesto por 100
multiplicar precio por ese resultado para obtener el impuesto
sumar el impuesto al precio
devolver el totalVale la pena notar algo de esta versión: los resultados intermedios se nombran de forma vaga ("ese resultado", "el impuesto", "el total"). A este nivel alcanza, porque el objetivo es fijar el orden de las operaciones. Darles un nombre preciso a esos valores intermedios es exactamente el tema de las variables, y tiene su propio lugar más adelante en la serie.
Un curso se aprueba con 60 puntos o más. Escribir el algoritmo que, a partir del puntaje obtenido, indica si la persona aprobó o no.
Este enunciado se parece al anterior, pero esconde una diferencia importante. En el ejercicio del precio, el resultado siempre se calculaba de la misma manera: cambiaban los números, no los pasos. Acá no. Según cuánto valga el puntaje, el algoritmo tiene que devolver una cosa u otra, así que los pasos que se ejecutan dependen del dato que entra.
algoritmo resultado_del_curso(puntaje):
si puntaje es mayor o igual a 60:
devolver "aprobado"
sino:
devolver "desaprobado"Aparecen dos palabras nuevas, si y sino, y una indentación de segundo nivel: los pasos que van adentro de cada rama se corren un poco más a la derecha, para que se lea de un vistazo cuáles se ejecutan en cada caso. Eso es una decisión, la primera herramienta de verdad de esta serie, y tiene un post entero dedicado más adelante. Acá aparece solo porque el problema la pedía y no había forma honesta de resolverlo sin ella.
Lo importante es que el algoritmo sigue cumpliendo las tres condiciones de antes: termina, cada paso significa una sola cosa, y queda claro qué entra y qué sale. Y sigue siendo independiente del lenguaje: en JavaScript esa decisión se escribe con if y else, en Python con if y else, en otros lenguajes con otras palabras, pero la forma de la solución no cambia.
El algoritmo es la solución; el programa es esa solución escrita en un lenguaje concreto. Cambiar de lenguaje cambia el programa y no cambia el algoritmo, así que un algoritmo mal pensado no mejora al traducirlo. Pensar los pasos antes de escribir código no es un paso previo opcional: es el trabajo.
Los dos enunciados de este post venían ya ordenados, con los datos de entrada servidos y el resultado esperado dicho de forma explícita. Fuera de un post, casi nunca es así: los enunciados traen datos que no hacen falta, restricciones escondidas en una frase al pasar y resultados descritos a medias. El próximo paso de la serie trata cómo leerlos, que es la habilidad que decide si el algoritmo que se escriba después resuelve el problema correcto.