Cerrábamos la lección anterior con tareafacil.py funcionando y una limitación evidente: todo lo que hace es imprimir texto fijo, y cambiar un dato obliga a editar el código a mano. La tentación ahora es lanzarse a aprender sintaxis para arreglarlo. Vamos a resistirla una lección más, porque falta la habilidad que de verdad separa a quien programa de quien copia código: pensar la solución antes de escribirla.

Un programador con prisa abre el editor y empieza a teclear. A las dos horas tiene código que casi funciona, no sabe por qué falla y no puede explicarle a nadie qué hace. Un programador con oficio dedica los primeros veinte minutos a papel: entiende el problema, lo descompone, escribe los pasos y los comprueba a mano. Después teclea, y teclea poco, porque ya sabe qué va a escribir.

En esta lección aprenderás qué es exactamente un algoritmo, cómo descomponer un problema, cómo expresar una solución en pseudocódigo y en diagrama de flujo, y cómo verificarla sin ordenador mediante una prueba de escritorio. Todo aplicado a dos operaciones reales de TareaFácil.

Aparecerán construcciones como «repetir» o «si...entonces»: aquí las usaremos solo como forma de pensar. Escribirlas en Python es asunto de los módulos 2 y 3.

Contenido

  1. Qué es un algoritmo
  2. Las cinco propiedades de un algoritmo
  3. Descomponer un problema en pasos y subproblemas
  4. Pseudocódigo: convenciones y ejemplo
  5. Diagramas de flujo
  6. Prueba de escritorio: verificar sin ordenador
  7. Del pseudocódigo al código Python
  8. TareaFácil: registrar una tarea nueva
  9. TareaFácil: qué tarea atiende Marta primero
  10. Errores comunes y consejos
  11. Ejercicios
  12. Conclusión

  1. Qué es un algoritmo

Un algoritmo es una secuencia finita de pasos precisos que, partiendo de unos datos de entrada, produce un resultado en un tiempo finito.

La palabra suena técnica, pero el concepto es cotidiano: una receta de cocina, las instrucciones de montaje de una estantería y el procedimiento de la multiplicación que aprendiste en el colegio son algoritmos. Comparten lo esencial: pasos ordenados, sin ambigüedad, que terminan y producen algo.

Lo importante es esto: un algoritmo es independiente del lenguaje de programación. El mismo algoritmo para ordenar una lista se puede escribir en Python, en Java o en papel; lo que cambia es la notación, no la idea. Por eso lo que aprendas aquí te servirá aunque cambies de lenguaje diez veces.

Concepto Qué es Analogía
Problema Lo que hay que resolver «Quiero un pastel»
Algoritmo El método para resolverlo La receta
Programa El algoritmo escrito en un lenguaje ejecutable La receta traducida a órdenes para un robot de cocina
Ejecución El programa funcionando con datos concretos Hacer el pastel el sábado

Confundir estas cuatro cosas es el origen de mucha frustración. «No me sale el programa» suele significar en realidad «no tengo claro el algoritmo», y eso no se arregla tocando código.

  1. Las cinco propiedades de un algoritmo

No toda lista de pasos es un algoritmo. Debe cumplir cinco propiedades.

1. Preciso. Cada paso indica exactamente qué hacer, sin margen de interpretación.

  • Mal: «revisa las tareas importantes».
  • Bien: «para cada tarea, si su prioridad es alta y su estado es pendiente, muéstrala por pantalla».

2. Definido (determinista). Con las mismas entradas produce siempre las mismas salidas. Si ejecutas el algoritmo dos veces con los mismos datos, el resultado es idéntico.

3. Finito. Termina después de un número finito de pasos. Un algoritmo que no termina no es un algoritmo, es un bucle infinito, y es uno de los errores más habituales al empezar.

  • Mal: «repite: cuenta una tarea más» (nunca acaba).
  • Bien: «repite mientras queden tareas por revisar» (acaba, porque las tareas son finitas y en cada vuelta queda una menos).

4. Con entrada definida. Cero o más datos de partida, especificados con claridad. En «registrar una tarea», la entrada son el título, la descripción, el responsable y la prioridad.

5. Con salida definida. Al menos un resultado observable: un valor, un mensaje en pantalla, un fichero modificado. Un algoritmo que no produce nada observable no sirve para nada.

Propiedad Pregunta de control Si falla...
Preciso ¿Puede alguien interpretar este paso de dos formas? El programa hará algo inesperado
Definido ¿Dará siempre el mismo resultado con los mismos datos? Errores imposibles de reproducir
Finito ¿Está garantizado que termina? El programa se cuelga
Entrada definida ¿Qué datos necesito y de dónde salen? Faltarán datos a mitad de ejecución
Salida definida ¿Qué produce y cómo lo veo? Nadie sabrá si funcionó

Aplica estas cinco preguntas a cualquier algoritmo que escribas. Detectan la mayoría de los fallos antes de que existan.

  1. Descomponer un problema en pasos y subproblemas

La técnica central para atacar cualquier problema se llama descomposición: partir un problema grande en problemas más pequeños hasta que cada pieza sea evidente. Se resuelve cada pieza por separado y luego se combinan.

Aplicado a TareaFácil, la petición inicial de Marta era: «quiero un programa para gestionar las tareas del estudio». Así, en bloque, es inabordable. Descompuesta:

flowchart TD
    A["Gestionar las tareas de Estudio Alba"] --> B["Registrar una tarea"]
    A --> C["Consultar tareas"]
    A --> D["Actualizar tareas"]
    A --> E["Guardar la informacion"]
    B --> B1["Pedir los datos"]
    B --> B2["Validar prioridad y responsable"]
    B --> B3["Anadir a la lista"]
    C --> C1["Listar todas"]
    C --> C2["Filtrar por responsable"]
    C --> C3["Filtrar por estado"]
    D --> D1["Marcar como completada"]
    D --> D2["Cambiar responsable"]

Cada hoja del árbol es una tarea pequeña que sí sabemos abordar. «Marcar como completada» es un problema manejable; «gestionar las tareas del estudio» no lo era.

La descomposición aporta tres ventajas concretas:

  • Progreso visible. Resolver una hoja del árbol lleva minutos, y ves avance. Enfrentarte al problema entero produce parálisis.
  • Errores localizados. Si falla el filtrado por responsable, sabes exactamente qué pieza mirar.
  • Reutilización. «Validar prioridad» sirve tanto al registrar una tarea como al modificarla. Escribirlo una vez y usarlo dos veces es la base del módulo 4.

Un criterio práctico para saber cuándo parar de descomponer: cuando puedas explicar la pieza en una frase y sepas cómo hacerla a mano. Si aún dudas, sigue partiendo.

  1. Pseudocódigo: convenciones y ejemplo

El pseudocódigo es una forma de escribir algoritmos a medio camino entre el español y el código: lo bastante estructurado para no ser ambiguo, lo bastante libre para no pelearse con la sintaxis.

No existe un pseudocódigo oficial. Estas son las convenciones que usaremos en el curso:

Elemento Notación Ejemplo
Inicio y fin INICIO / FIN
Entrada de datos LEER <dato> LEER titulo
Salida de datos MOSTRAR <mensaje> MOSTRAR "Tarea guardada"
Asignar un valor <nombre> ← <valor> contador ← 0
Condición SI <cond> ENTONCES ... SINO ... FIN SI
Repetición condicional MIENTRAS <cond> HACER ... FIN MIENTRAS
Repetición sobre elementos PARA CADA <x> EN <lista> HACER ... FIN PARA
Comentario // texto // se ignora al ejecutar

Dos reglas de estilo importantes: indenta el contenido de cada bloque (facilita ver dónde empieza y acaba) y cierra siempre los bloques (FIN SI, FIN MIENTRAS).

Ejemplo completo. Algoritmo que calcula cuántas tareas pendientes tiene el estudio:

INICIO
    // Entrada: una lista de tareas, cada una con su estado
    // Salida: el numero de tareas pendientes

    pendientes ← 0

    PARA CADA tarea EN lista_de_tareas HACER
        SI estado de tarea = "pendiente" ENTONCES
            pendientes ← pendientes + 1
        FIN SI
    FIN PARA

    MOSTRAR "Tareas pendientes: " + pendientes
FIN

Repasemos las cinco propiedades sobre este algoritmo:

  • Preciso: cada paso es inequívoco.
  • Definido: la misma lista produce siempre el mismo número.
  • Finito: la lista tiene un número finito de elementos y cada vuelta consume uno.
  • Entrada definida: la lista de tareas con sus estados.
  • Salida definida: un mensaje con el número de pendientes.

Cumple las cinco. Es un algoritmo correcto, y lo hemos verificado sin encender el ordenador.

  1. Diagramas de flujo

Un diagrama de flujo representa el algoritmo gráficamente. Es especialmente útil cuando hay decisiones y caminos alternativos, porque se ven de un vistazo.

Los símbolos básicos:

Símbolo Forma Significado
Inicio / Fin Óvalo Dónde empieza y acaba
Proceso Rectángulo Una acción o cálculo
Decisión Rombo Una pregunta con salidas Sí/No
Entrada / Salida Romboide Leer datos o mostrar resultados
Flecha Orden en que se avanza

Ejemplo 1: ¿la tarea es urgente? Un algoritmo con una sola decisión.

flowchart TD
    A(["INICIO"]) --> B[/"LEER prioridad de la tarea"/]
    B --> C{"prioridad = alta?"}
    C -->|Si| D[/"MOSTRAR: Atender hoy"/]
    C -->|No| E[/"MOSTRAR: Puede esperar"/]
    D --> F(["FIN"])
    E --> F

Fíjate en dos cosas: del rombo salen exactamente dos flechas etiquetadas, y ambos caminos vuelven a unirse antes del fin. Un diagrama con caminos que no acaban en FIN está incompleto.

Ejemplo 2: contar las tareas pendientes. El mismo algoritmo del apartado anterior, ahora con repetición.

flowchart TD
    A(["INICIO"]) --> B["pendientes ← 0"]
    B --> C["Situarse en la primera tarea"]
    C --> D{"Quedan tareas<br/>por revisar?"}
    D -->|No| H[/"MOSTRAR pendientes"/]
    D -->|Si| E{"Su estado es<br/>pendiente?"}
    E -->|Si| F["pendientes ← pendientes + 1"]
    E -->|No| G["Pasar a la siguiente tarea"]
    F --> G
    G --> D
    H --> I(["FIN"])

El bucle se ve como lo que es: una flecha que vuelve hacia atrás, de G a D. Y ahí está la clave de la finitud: G avanza a la siguiente tarea en cada vuelta, así que en algún momento la respuesta a D será «No». Si G no existiera, el diagrama giraría para siempre. Esa flecha de retorno es el bucle infinito hecho visible, y es un buen motivo para dibujar antes de programar.

Herramienta Cuándo conviene
Pseudocódigo Algoritmos largos, muchos pasos secuenciales, cerca ya del código
Diagrama de flujo Pocos pasos pero muchas decisiones; explicar la lógica a otra persona

En la práctica se usan las dos: el diagrama para entender la forma general, el pseudocódigo para el detalle.

  1. Prueba de escritorio: verificar sin ordenador

La prueba de escritorio (o trazado) consiste en ejecutar el algoritmo a mano, con datos concretos, anotando en una tabla cómo cambia cada valor paso a paso. Es la técnica más infravalorada y más rentable de todo el oficio: detecta errores de lógica en cinco minutos que en el ordenador costarían una hora.

Tracemos el algoritmo de contar pendientes con estos datos de Estudio Alba:

Tarea Responsable Estado
1 Logotipo Panadería Solé Luis pendiente
2 Cartel feria del libro Nuria completada
3 Rediseño web cliente Vidal Luis pendiente
4 Presupuesto marzo Marta pendiente

Y ahora la tabla de trazado. Una fila por vuelta del bucle, una columna por valor que nos interesa:

Vuelta Tarea examinada Estado ¿Es pendiente? pendientes después
(inicio) 0
1 Logotipo Panadería Solé pendiente 1
2 Cartel feria del libro completada No 1
3 Rediseño web cliente Vidal pendiente 2
4 Presupuesto marzo pendiente 3
(fin: no quedan tareas) 3

Salida: Tareas pendientes: 3. Contando a ojo en la tabla de datos: la 1, la 3 y la 4. Correcto.

Cómo hacer una prueba de escritorio bien:

  1. Elige datos pequeños pero representativos. Cuatro elementos bastan; con cuarenta te cansarás y te saltarás pasos.
  2. Una columna por cada valor que cambie. Si hay tres variables, tres columnas.
  3. Una fila por paso o vuelta. Sin agrupar ni «ir más rápido»: el error suele estar precisamente donde uno da algo por supuesto.
  4. Sé la máquina, no el autor. No hagas lo que querías escribir, haz lo que está escrito. Aquí es donde aparecen los errores.
  5. Prueba también los casos límite. ¿Y si la lista está vacía? Con nuestro algoritmo, el bucle no se ejecuta ninguna vez y la salida es 0. Correcto. ¿Y si todas están completadas? También 0. Correcto.

Ese último punto merece énfasis: los casos límite son donde vive la mayoría de los errores reales. Lista vacía, un solo elemento, todos iguales, valores repetidos. Compruébalos siempre.

  1. Del pseudocódigo al código Python

Cuando el algoritmo está claro y trazado, traducirlo a Python es casi mecánico. Veámoslo con un ejemplo que ya podemos escribir entero: mostrar la ficha de una tarea.

Pseudocódigo:

INICIO
    MOSTRAR "--- FICHA DE TAREA ---"
    MOSTRAR "Titulo: Logotipo Panaderia Sole"
    MOSTRAR "Responsable: Luis"
    MOSTRAR "Prioridad: alta"
    MOSTRAR "Estado: pendiente"
FIN

Python:

print("--- FICHA DE TAREA ---")
print("Titulo: Logotipo Panaderia Sole")
print("Responsable: Luis")
print("Prioridad: alta")
print("Estado: pendiente")

La correspondencia es directa: MOSTRAR se convierte en print, y el texto va entre comillas dentro de los paréntesis. INICIO y FIN no se traducen: en Python el programa empieza en la primera línea y acaba en la última.

Esta es la tabla de traducción completa que iremos completando a lo largo del curso:

Pseudocódigo Python Dónde se estudia
MOSTRAR x print(x) Ya lo sabes
LEER x x = input() Entrada y salida
x ← 5 x = 5 Variables
SI ... ENTONCES if ...: Condicionales
SINO else: Condicionales
MIENTRAS ... HACER while ...: Bucles
PARA CADA x EN lista for x in lista: Bucles

De momento solo tienes la primera fila. Al terminar el módulo 3 tendrás todas, y podrás traducir a Python cualquier algoritmo que escribas en pseudocódigo. Mientras tanto, escribe pseudocódigo sin miedo: el algoritmo es lo valioso, y traducirlo será lo fácil.

  1. TareaFácil: registrar una tarea nueva

Vamos a aplicar todo lo anterior al primer requisito de TareaFácil (R1 y R2 de la lista de la primera lección): registrar una tarea con sus cinco datos, validando la prioridad.

El problema. Marta quiere apuntar un encargo nuevo. Hay que pedirle título, descripción, responsable y prioridad; el estado siempre empieza como «pendiente». La prioridad solo puede ser alta, media o baja: si escribe otra cosa, hay que volver a preguntar.

Pseudocódigo:

INICIO
    // Entrada: datos tecleados por el usuario
    // Salida: la tarea registrada y un mensaje de confirmacion

    MOSTRAR "--- NUEVA TAREA ---"

    LEER titulo
    LEER descripcion
    LEER responsable

    // Validacion: repetir hasta que la prioridad sea valida
    prioridad_valida ← FALSO
    MIENTRAS prioridad_valida = FALSO HACER
        MOSTRAR "Prioridad (alta / media / baja):"
        LEER prioridad
        SI prioridad = "alta" O prioridad = "media" O prioridad = "baja" ENTONCES
            prioridad_valida ← VERDADERO
        SINO
            MOSTRAR "Prioridad no valida. Intentalo de nuevo."
        FIN SI
    FIN MIENTRAS

    estado ← "pendiente"

    GUARDAR la tarea (titulo, descripcion, responsable, prioridad, estado)
    MOSTRAR "Tarea registrada correctamente."
FIN

Diagrama de flujo:

flowchart TD
    A(["INICIO"]) --> B[/"LEER titulo, descripcion,<br/>responsable"/]
    B --> C[/"LEER prioridad"/]
    C --> D{"prioridad es<br/>alta, media o baja?"}
    D -->|No| E[/"MOSTRAR: prioridad no valida"/]
    E --> C
    D -->|Si| F["estado ← pendiente"]
    F --> G["GUARDAR la tarea"]
    G --> H[/"MOSTRAR: tarea registrada"/]
    H --> I(["FIN"])

Fíjate en la flecha que vuelve de E a C: es el bucle de validación. Mientras la prioridad sea incorrecta, se vuelve a preguntar. Y es finito siempre que el usuario acabe escribiendo algo válido; si teclea disparates indefinidamente, el programa preguntará indefinidamente. Eso no es un error del algoritmo: es una decisión de diseño que conviene tomar conscientemente. Una alternativa sería permitir tres intentos y cancelar.

Prueba de escritorio. Marta registra un encargo y se equivoca al escribir la prioridad:

Paso Acción Valor introducido Estado del algoritmo
1 LEER titulo «Tarjetas de visita Vidal» titulo asignado
2 LEER descripcion «300 uds, doble cara» descripcion asignada
3 LEER responsable «Nuria» responsable asignado
4 LEER prioridad «urgente» no es válida → mensaje de error
5 LEER prioridad «ALTA» ¿es válida?
6 LEER prioridad «alta» válida → sale del bucle
7 estado ← pendiente estado = «pendiente»
8 GUARDAR y MOSTRAR «Tarea registrada correctamente.»

El paso 5 revela un problema que la prueba de escritorio ha hecho aflorar: «ALTA» en mayúsculas no coincide con «alta», porque son textos distintos. El algoritmo, tal y como está escrito, la rechazaría. ¿Es lo que queremos? Casi seguro que no: Marta escribirá en mayúsculas la mitad de las veces.

La corrección es sencilla —convertir lo introducido a minúsculas antes de comparar— y la aplicaremos en Conversión de tipos y validación. Lo relevante aquí es cómo hemos encontrado el fallo: con una tabla y un lápiz, antes de escribir una sola línea de Python. Encontrarlo más tarde, con el programa ya escrito, habría costado mucho más.

  1. TareaFácil: qué tarea atiende Marta primero

Segundo algoritmo, esta vez de decisión. Marta llega el lunes, tiene varias tareas asignadas y quiere saber por cuál empezar.

La regla de negocio, acordada con el equipo:

  1. Solo cuentan las tareas pendientes: las completadas se ignoran.
  2. Entre las pendientes, gana la de prioridad más alta (alta > media > baja).
  3. Si hay empate de prioridad, gana la que se registró antes.

Fíjate en que estas tres reglas no las inventa el programador: se acuerdan con quien tiene el problema. Escribirlas explícitamente es parte del trabajo, y muchas veces la primera vez que el equipo se pone de acuerdo en algo que creía obvio.

Pseudocódigo:

INICIO
    // Entrada: lista de tareas de Marta, en orden de registro
    // Salida: la tarea que debe atender primero

    elegida ← NINGUNA

    PARA CADA tarea EN tareas_de_marta HACER

        SI estado de tarea = "completada" ENTONCES
            // no nos interesa, pasamos a la siguiente
        SINO
            SI elegida = NINGUNA ENTONCES
                elegida ← tarea
            SINO
                SI prioridad de tarea es mayor que prioridad de elegida ENTONCES
                    elegida ← tarea
                FIN SI
                // si es igual o menor, se mantiene la anterior:
                // asi gana la registrada antes en caso de empate
            FIN SI
        FIN SI

    FIN PARA

    SI elegida = NINGUNA ENTONCES
        MOSTRAR "No tienes tareas pendientes."
    SINO
        MOSTRAR "Empieza por: " + titulo de elegida
    FIN SI
FIN

Diagrama de flujo:

flowchart TD
    A(["INICIO"]) --> B["elegida ← NINGUNA"]
    B --> C{"Quedan tareas<br/>por revisar?"}
    C -->|No| J{"elegida = NINGUNA?"}
    C -->|Si| D{"Esta completada?"}
    D -->|Si| I["Pasar a la siguiente"]
    D -->|No| E{"elegida = NINGUNA?"}
    E -->|Si| F["elegida ← tarea actual"]
    E -->|No| G{"Su prioridad es mayor<br/>que la de elegida?"}
    G -->|Si| F
    G -->|No| I
    F --> I
    I --> C
    J -->|Si| K[/"MOSTRAR: no hay pendientes"/]
    J -->|No| L[/"MOSTRAR: empieza por elegida"/]
    K --> M(["FIN"])
    L --> M

Prueba de escritorio. Las tareas de Marta, en orden de registro:

Título Prioridad Estado
1 Presupuesto cliente Vidal media pendiente
2 Revisar facturas febrero baja completada
3 Llamar a Panadería Solé alta pendiente
4 Preparar reunión equipo alta pendiente

Trazado vuelta a vuelta:

Vuelta Tarea ¿Completada? elegida antes ¿Sustituye? elegida después
1 Presupuesto Vidal (media) No NINGUNA Sí, no había ninguna Presupuesto Vidal
2 Revisar facturas (baja) Presupuesto Vidal No, se ignora Presupuesto Vidal
3 Llamar a Solé (alta) No Presupuesto Vidal Sí: alta > media Llamar a Solé
4 Preparar reunión (alta) No Llamar a Solé No: alta no es mayor que alta Llamar a Solé

Salida: Empieza por: Llamar a Panadería Solé.

Verifiquemos que es correcto según las reglas acordadas. Pendientes hay tres: Presupuesto (media), Llamar a Solé (alta) y Preparar reunión (alta). De prioridad alta hay dos, y entre ellas gana la registrada antes, que es «Llamar a Solé» (número 3 frente a número 4). Coincide con lo que produce el algoritmo.

Y los casos límite:

  • Marta no tiene ninguna tarea. El bucle no se ejecuta, elegida sigue siendo NINGUNA y se muestra «No tienes tareas pendientes». Correcto.
  • Todas están completadas. Todas caen por la rama que las ignora, elegida sigue NINGUNA y sale el mismo mensaje. Correcto.
  • Solo una pendiente. Se asigna en su vuelta y ninguna la sustituye. Correcto.

El algoritmo aguanta los cuatro escenarios. Está listo para implementarse, y lo haremos cuando tengamos condicionales y bucles en Python.

Errores Comunes y Consejos

Empezar a teclear sin haber pensado el algoritmo. Es el error más caro. Si no sabes explicar en voz alta qué pasos va a dar tu programa, no estás listo para escribirlo. Papel primero.

Pasos ambiguos. «Comprobar si la tarea es importante» no es un paso: no dice qué significa importante. «Comprobar si su prioridad es alta» sí lo es. Toda ambigüedad que dejes en el algoritmo reaparecerá como error en el programa.

Olvidar el avance dentro de un bucle. Si en cada vuelta no cambia nada que acerque al final, el bucle es infinito. En el diagrama se ve enseguida: busca qué caja hace progresar la condición del rombo. Si no la encuentras, tienes un problema.

Saltarse los casos límite. Lista vacía, un solo elemento, todos con el mismo valor, todos completados. Un algoritmo que solo funciona con el caso bonito no funciona.

Hacer la prueba de escritorio «como autor» y no «como máquina». Al trazar tiendes a ejecutar lo que querías escribir, no lo que escribiste. Es la trampa más sutil. Truco: traza un algoritmo tuyo de hace una semana, o intercámbialo con otra persona.

Dar por supuestas reglas de negocio. «Gana la de prioridad más alta» parece completo hasta que dos tareas empatan. Escribe siempre qué pasa en los empates, en los vacíos y en los datos incorrectos. Preguntarlo antes es barato; descubrirlo en producción, no.

Creer que el pseudocódigo debe ser perfecto. No es un entregable, es una herramienta de pensamiento. Táchalo, reescríbelo, usa flechas al margen. Si te ayuda a pensar, está bien escrito.

Consejo final: cuando un programa te salga mal, no empieces cambiando código a ver si acierta. Vuelve al algoritmo y hazle una prueba de escritorio. En la mayoría de los casos el error no está en la sintaxis, está en el razonamiento.

Ejercicios

Ejercicio 1: Detectar propiedades incumplidas

Para cada algoritmo, indica qué propiedad o propiedades incumple y corrígelo:

a)

INICIO
    MIENTRAS haya tareas HACER
        MOSTRAR "Hay tareas pendientes"
    FIN MIENTRAS
FIN

b)

INICIO
    LEER prioridad
    SI la prioridad parece urgente ENTONCES
        MOSTRAR "Atender pronto"
    FIN SI
FIN

c)

INICIO
    contador ← 0
    PARA CADA tarea EN lista HACER
        contador ← contador + 1
    FIN PARA
FIN

Ejercicio 2: Algoritmo y diagrama para contar las tareas de una persona

Escribe el pseudocódigo y el diagrama de flujo de un algoritmo que, dada la lista de tareas del estudio y el nombre de una persona, muestre cuántas tareas pendientes tiene asignadas. Después, haz la prueba de escritorio con estos datos, buscando las de Luis:

Título Responsable Estado
1 Logotipo Panadería Solé Luis pendiente
2 Cartel feria del libro Nuria pendiente
3 Rediseño web Vidal Luis completada
4 Manual de marca Solé Luis pendiente
5 Presupuesto marzo Marta pendiente

Ejercicio 3: Reasignar una tarea

Marta quiere poder reasignar una tarea a otra persona del equipo. Las reglas acordadas son:

  • Solo se pueden reasignar tareas pendientes; una completada no se toca.
  • El nuevo responsable debe ser Marta, Luis o Nuria.
  • No tiene sentido reasignar a la misma persona que ya la tiene: hay que avisar.

Escribe el pseudocódigo de este algoritmo y haz una prueba de escritorio para estos tres casos: (a) reasignar a Nuria una tarea pendiente de Luis, (b) intentar reasignar una tarea completada, (c) reasignar a Luis una tarea que ya es de Luis.

Soluciones

Solución 1.

a) Incumple la finitud. Nada dentro del bucle reduce el número de tareas ni avanza por la lista, así que la condición nunca deja de cumplirse: se imprimiría el mensaje eternamente. Además no tiene salida útil (repite lo mismo sin informar de nada). Corrección:

INICIO
    pendientes ← 0
    PARA CADA tarea EN lista HACER
        SI estado de tarea = "pendiente" ENTONCES
            pendientes ← pendientes + 1
        FIN SI
    FIN PARA
    MOSTRAR "Tareas pendientes: " + pendientes
FIN

b) Incumple la precisión (y, por tanto, el determinismo). «Parece urgente» no es evaluable: dos personas lo interpretarían distinto y la máquina no puede interpretarlo en absoluto. Corrección:

INICIO
    LEER prioridad
    SI prioridad = "alta" ENTONCES
        MOSTRAR "Atender pronto"
    SINO
        MOSTRAR "Puede esperar"
    FIN SI
FIN

Se ha añadido el SINO para que haya salida en ambos casos.

c) Incumple la salida definida. Calcula correctamente el contador pero no lo muestra: el resultado se pierde al terminar. Corrección: añadir MOSTRAR "Total de tareas: " + contador antes de FIN.

Solución 2.

Pseudocódigo:

INICIO
    // Entrada: lista de tareas y nombre de una persona
    // Salida: numero de tareas pendientes de esa persona

    LEER persona
    contador ← 0

    PARA CADA tarea EN lista_de_tareas HACER
        SI responsable de tarea = persona Y estado de tarea = "pendiente" ENTONCES
            contador ← contador + 1
        FIN SI
    FIN PARA

    MOSTRAR persona + " tiene " + contador + " tareas pendientes."
FIN

Diagrama de flujo:

flowchart TD
    A(["INICIO"]) --> B[/"LEER persona"/]
    B --> C["contador ← 0"]
    C --> D{"Quedan tareas<br/>por revisar?"}
    D -->|No| H[/"MOSTRAR persona y contador"/]
    D -->|Si| E{"Es de esa persona<br/>Y esta pendiente?"}
    E -->|Si| F["contador ← contador + 1"]
    E -->|No| G["Pasar a la siguiente"]
    F --> G
    G --> D
    H --> I(["FIN"])

Prueba de escritorio buscando las de Luis:

Vuelta Tarea ¿Es de Luis? ¿Pendiente? ¿Cuenta? contador
(inicio) 0
1 Logotipo Panadería Solé 1
2 Cartel feria del libro No No 1
3 Rediseño web Vidal No No 1
4 Manual de marca Solé 2
5 Presupuesto marzo No No 2

Salida: Luis tiene 2 tareas pendientes. Verificado a ojo: la 1 y la 4. La 3 es de Luis pero está completada, y ese es justamente el caso que comprueba que la condición doble funciona.

Solución 3.

INICIO
    // Entrada: una tarea y el nombre del nuevo responsable
    // Salida: la tarea reasignada, o un mensaje explicando por que no

    LEER tarea
    LEER nuevo_responsable

    SI estado de tarea = "completada" ENTONCES
        MOSTRAR "No se puede reasignar: la tarea ya esta completada."
    SINO
        SI nuevo_responsable NO ES "Marta" NI "Luis" NI "Nuria" ENTONCES
            MOSTRAR "Responsable no valido. Debe ser Marta, Luis o Nuria."
        SINO
            SI nuevo_responsable = responsable de tarea ENTONCES
                MOSTRAR "La tarea ya esta asignada a " + nuevo_responsable
            SINO
                responsable de tarea ← nuevo_responsable
                MOSTRAR "Tarea reasignada a " + nuevo_responsable
            FIN SI
        FIN SI
    FIN SI
FIN

Prueba de escritorio:

Caso Tarea (responsable, estado) Nuevo responsable Comprobaciones Resultado
a Logotipo Solé (Luis, pendiente) Nuria No completada → responsable válido → distinto del actual responsable ← Nuria. «Tarea reasignada a Nuria»
b Rediseño web Vidal (Luis, completada) Nuria Completada → se corta en la primera condición «No se puede reasignar: la tarea ya está completada.»
c Manual de marca (Luis, pendiente) Luis No completada → responsable válido → igual al actual Sin cambios. «La tarea ya está asignada a Luis»

Observa el orden de las comprobaciones: primero el estado, después la validez del nombre y por último la coincidencia. Ese orden importa. Si comprobásemos primero si coincide el responsable, una tarea completada asignada a Luis que se intentase reasignar a Luis daría el mensaje equivocado. Decidir en qué orden se hacen las comprobaciones es parte del diseño del algoritmo, no un detalle.

Conclusión

Programar empieza lejos del teclado. En esta lección has aprendido que un algoritmo es una secuencia finita de pasos precisos que transforman una entrada en una salida, independiente del lenguaje en que se escriba, y que debe cumplir cinco propiedades: ser preciso, definido, finito, con entrada definida y con salida definida. Has visto cómo descomponer un problema grande en subproblemas manejables, cómo expresar la solución en pseudocódigo con convenciones claras y cómo dibujarla en un diagrama de flujo donde los bucles se ven como flechas que vuelven atrás. Y has practicado la técnica más rentable del oficio: la prueba de escritorio, que con una tabla y un lápiz encuentra errores que en el ordenador costarían horas —como el «ALTA» que no coincidía con «alta».

Todo ello aplicado a TareaFácil: ya tenemos diseñados, verificados y con sus casos límite comprobados los algoritmos de registrar una tarea nueva y de decidir qué tarea atiende Marta primero. No son bocetos: son especificaciones listas para implementar.

Con esto cerramos el módulo 1. Sabes qué es programar, de dónde viene el oficio, cómo se clasifican y eligen los lenguajes, tienes un entorno funcionando con tareafacil.py en tu disco y sabes diseñar un algoritmo antes de escribirlo. Es exactamente el equipaje que hace falta para empezar a escribir código de verdad.

Y ahí vamos ahora. En el módulo 2 dejamos el papel y volvemos a Python con la pieza que resuelve la limitación que arrastramos desde la lección anterior —un programa que solo imprime texto fijo—: las variables, que permiten guardar datos y trabajar con ellos. Empezaremos por Variables y tipos de datos, donde por fin el título, el responsable y la prioridad de una tarea dejarán de estar escritos a mano dentro de un print y pasarán a ser información que el programa maneja.

Fundamentos de la Programación

Módulo 1: Introducción a la Programación

Módulo 2: Conceptos Básicos

Módulo 3: Estructuras de Control

Módulo 4: Funciones y Procedimientos

Módulo 5: Estructuras de Datos

Módulo 6: Algoritmos Básicos

Módulo 7: Objetos y Organización del Código

Módulo 8: Buenas Prácticas y Herramientas

Módulo 9: Proyecto Final y Cierre del Curso

© Copyright 2026. Todos los derechos reservados