Acá vamos a hablar sobre algoritmos, la lógica de la programación, lo fundamental a la hora de escribir un programa.
# Algoritmos
Nuestros programas están escritos con algoritmos. Un algoritmo es una secuencia de pasos que nos permite resolver un problema, lograr un objetivo.
Seguramente escuchaste hablar del algoritmo de Youtube, de Tiktok, de Instagram, en base a lo que ves te recomienda lo que cree que podés ver.
Va registrando lo que vemos, lo memoriza, lo procesa y retorna el resultado, lo que cree que queremos ver, la salida.
Debemos aprender a escribir esta lógica básica, el ejemplo más común es la receta de cocina: “Poner 500g de harina, poner dos huevos, poner 10g de azúcar, mezclarâ€.
Bien específico. No digo: “poner harinaâ€, digo la cantidad que tengo que poner. Debo aclarar todo lo necesario para que no haya confusión y debe estar en el orden correcto (no puedo primero mezclar y después poner la harina).
Nuestros algoritmos se escriben dentro de bloques de código. Tienen un inicio, tienen un fin (para que se sepa dónde comienza y dónde termina) y en el interior está nuestro bloque, las acciones que ejecuta, el proceso.
Todo algoritmo se puede escribir con 3 estructuras, sí! nada más que 3!
- 1. La estructura secuencial: va línea a línea en un orden concreto.
- 2. La estructura condicional: permite elegir un camino u otro, o varios.
- 3. La estructura repetitiva o los ciclos: permiten repetir la ejecución de un bloque de código.
Conociendo bien estas estructuras podemos escribir cualquier algoritmo.
# Variables
Vimos que hay una entrada, una memorización, un proceso y una salida. Para guardar esta entrada (memorizar) tenemos unas cajita se llaman variables. Estas variables nos permiten ir almacenando elementos qué podemos usar a lo largo de nuestro programa.
La podemos ver como unas cajita en la que guardamos un valor, lo modificamos, lo vemos.
Estas cajitas son de un tipo específico, una cajita puede guardar un valor entero, un valor decimal, una palabra, una letra, un booleano (verdadero o falso). Ese tipo específico es el tipo de dato que puede guardar la variable.
Si tenemos una caja de tipo entero, no vamos a poder guardar un decimal, ni una palabra.
Además de un tipo de dato y de un valor (lo que guardamos dentro de la cajita), la variable tiene un identificador, un nombre.
Por ejemplo, llamo a mi variable “edadâ€, ese el nombre que tiene la variable. Con ese nombre la puedo usar para darle valor, para modificar su valor, o para verlo.
Los nombres de las variables deben ser representativos, por ejemplo “int edad†sé que estoy representando una edad. Pero si a mi variable le pongo “aâ€, no sé qué significa. Si estoy en un programa que tiene algunas líneas, no pasa nada, pero en un programa con miles, cientos de miles, de líneas, se hace más difícil entenderlo, y nuestro trabajo siempre es hacerle la vida más fácil a otros programadores (incluso a nosotros mismos si tenemos que volver a ver ese código).
En realidad, en el proceso computacional, una variable es una posición de memoria en donde se guarda el valor. El tamaño de esa posición de memoria va a depender del tipo de dato que guardemos.
# Operadores
Para guardar algo en la cajita (en la posición de memoria) tengo operadores que permiten trabajar con variables.
El operador de asignación (voy a considerar que se representa con el signo igual (“=â€), que se usa en muchos lenguajes) permite dar valor a una variable.
int edad = 20; // Asignación inicial
edad = 10; // Re-asignación (pisa el valor anterior)
Por ejemplo: int edad = 20 (a la variable edad le asigno el valor 20). Esto quiere decir que estoy guardando el valor 20 dentro de mi cajita edad. Si ahora hago edad = 10, estoy pisando el valor anterior, y dejándole un valor nuevo, ya se perdió el 20, ahora vale 10.
Y así como está el operador de asignación, hay operadores aritméticos, que permiten sumar, restar, multiplicar, dividir.
Puedo sumar valores, puedo sumar variables, puedo tener dos variables, las sumo, guardo el resultado en otra.
El valor de la variable suma, el resultado, la salida, es 5. Puedo armar un programa simple para calcular el promedio entre tres números. Tengo que declarar las variables de entrada numero1, numero2, numero3, a cada una le asigno un valor. La salida la tengo que guardar en algún lado, así que voy a declarar una variable para calcular el promedio. Puedo incluso usar una variable intermedia para guardar la suma de los tres valores, suma.
Lo que hicimos fue asignarle valores a las variables numero1, numero2 y numero3, pero como programadores no hacemos eso, queremos que los datos los ingrese el usuario, así que debemos pedirle que ingrese esos tres valores. Para esto, los lenguajes nos dan unas funciones primitivas, que interactúan con el sistema operativo, con las que podemos ingresar datos y mostrarlos en pantalla. Voy a usar la primitiva read para cargar un dato en una variable y voy a usar la primitiva print para mostrar en pantalla lo que envío.
Cada lenguaje tiene su propia sintaxis, acá estamos definiendo la nuestra “read†para leer, “print†para imprimir. Cuando usamos un lenguaje nos adaptamos a la sintaxis del lenguaje, acá estamos creando un pseudocódigo (forma de escribir código combinando lenguaje natural con lenguaje de programación).
Así que en este caso el algoritmo quedaría así:
- Hago un print imprimo “Ingrese el número 1â€, hago un read(numero1). Repito para numero2 y numero3.
- Hago la operación, la suma de los 3 números y calculo el promedio dividiendo la suma por 3.
- Finalmente imprimo el resultado, el valor de la variable promedio.
# Estructuras de Control
// Secuencial
Este ejemplo es secuencial, va línea a línea, no hay ningún cambio en el recorrido, no cambia el orden en ningún momento.
// Condicional
Supongamos ahora que queremos imprimir si el alumno aprobó, el alumno recupera, o el alumno recursa. De forma secuencial no podemos hacerlo, tenemos que analizar la nota y en base al valor de la nota ir por uno de estos tres caminos.
Tenemos que evaluar una condición, si es verdadera vamos por un camino, si es falsa vamos por otro, que puede ser uno o varios caminos. Así que acá lo que necesitamos es una estructura condicional el Sí, el If.
if (condicion) {
// Acciones si es TRUE
} else {
// Acciones si es FALSE
}
Si la condición que ponemos entre paréntesis es verdadera (true), se ejecutan las acciones1 y 2, sino la 3 y la 4. Pero tambien podemos tener más de una condición:
En este caso, si la condicion1 es true, se ejecutan las acciones accion1 y accion2; sino, evalúa la siguiente condicion, la condicion2. Si es verdadera ejecuta las acciones accion3 y accion4, sino evalúa la condicion3… y así hasta el final. Si no se cumple ninguna, entra por el else.
Para determinar si una condición es verdadera o falsa (valor booleano) tenemos operadores de comparación:
Usando estos operadores, armamos el algoritmo:
Si nota es mayor o igual a 7 imprimo que aprobó, sino si nota es mayor o igual a 4 imprimo recupera. Este caso implica que la nota va a estar entre 4 y 6 porque si no hubiera entrado por el mayor o igual a 7. Y sino, en este caso la nota es menor a 4, imprimo que recursa. Pudimos agregar tres condiciones usando un mismo bloque If.
Operadores lógicos
Qué pasa si queremos agregar más de una condición en una misma sentencia, en una misma línea. Podemos hacerlo porque tenemos operadores lógicos el “AND†(Y) y el “OR†(O) que conectan dos expresiones, cada expresión con su propio valor de verdad (True o False).
En el caso del AND, si las dos expresiones son Verdaderas, el resultado es Verdadero. En cualquier otro caso es Falso.
Si lo aplicamos a un if, para buscar notas entre 4 y 6:
En el caso del OR, si las dos expresiones son Falsas, el resultado es Falso. En todo otro caso es Verdadero.
Si lo aplicamos a un if para saber si estoy en un fin de semana:
// Ciclos (Loops)
Los ciclos son estructuras que nos permiten repetir la ejecución de una o varias acciones.
¿Para qué nos sirve repetir?
Por ejemplo, podemos pedir al usuario que ingrese los datos de varios empleados, o también para recorrer una serie de elementos. Es una de las estructuras fundamentales, de las más difíciles de entender, pero se usa todo el tiempo en programación.
Consideraciones para su uso
Debemos pensar qué es lo que tenemos que repetir, cuáles son las instrucciones que debemos repetir.
Puedo pedir al usuario que ingrese números e ir sumando esos números, ir acumulando los valores que ingresan.
Si pongo estas dos instrucciones read (numero) y sumar (numero) y lo meto dentro de un ciclo sin control, se va a repetir eternamente. Así que lo siguiente que debo considerar es cuántas veces se tiene que repetir. Y para esto tenemos 3 tipos de ciclos:
WHILE (mientras)
Depende de una condición, mientras se cumple la condición se va a repetir el ciclo. Se analiza la condición, si se cumple, se ingresa. Y cuando termina de ejecutar las acciones dentro, vuelve a evaluar. Es importante que dentro cambien los valores para que no se genere un ciclo infinito.
El ejemplo con un while podría quedar así. Leemos el número, si es mayor a cero ingresamos al ciclo, lo sumamos (inicializando suma en cero), y volvemos a leer numero para cambiar el valor de la variable que controla la condición.
Notemos algo… al principio leemos la variable numero. Si el valor ingresado es menor o igual a cero, no ingresa al ciclo, por lo que puede que este ciclo nunca se ejecute.
DO/WHILE (hacer/mientras)
Si queremos que se ejecute mínimo una vez. Primero hace, después pregunta. Primero ingresa al ciclo y ejecuta las acciones, cuando termina evalúa la condición.
Para el ejemplo: leo numero, controlo que numero sea mayor a cero para sumar, y agrego la condición al final.
FOR (para)
Se usa cuando sabemos la cantidad exacta de veces que se debe repetir. Tiene una variable que actúa como contador.
Por ejemplo, si ingresamos 10 números, podríamos usar un for de 0 a 9. En el segundo caso inicializamos la variable con 0, ejecutamos mientras sea menor o igual a 9, e incrementamos automáticamente cada vez que repite.
Lo importante es que para repetir tenemos estas tres instrucciones. Podemos usar las tres para todo ciclo, pero según lo que tengamos que hacer uno se va a adaptar mejor que otro.
Rompiendo ciclos
También tenemos sentencias para cambiar la secuencia de los ciclos: continue para saltar a la siguiente iteración, y break para salir del ciclo. No son recomendables porque rompen el flujo natural, pero se usan.
Continue
Break
Hasta aquí llegamos con algoritmos. Estos son los temas básicos que debe dominar un programador, y la única forma de lograrlo es practicando. No alcanza con solo leer teoría, hacer ejercicios de lógica de programación es fundamental.
En el próximo capítulo veremos funciones, algo fundamental a la hora de programar, ya que facilita la resolución de problemas y permite el trabajo en equipo.