Ejercicios — Programación I

Cada bloque tiene enunciado, una pista y una solución escondida. Probá vos primero. La respuesta se revela tocando "Ver solución".

Los ejercicios están agrupados por capítulo y graduados de fácil a difícil. La pista y la solución están dentro de <details>: hacé clic para abrir.


Cap. 1 — Algoritmos y pseudocódigo

1.1 — Receta a algoritmo (básico)

Escribí en pseudocódigo el algoritmo para preparar pupusas: ingredientes, pasos, criterio de "listo".

💡 Pista

Pensá en inputs (qué necesitás) y outputs (qué obtenés). Los pasos deben ser tan concretos que cualquiera los pueda seguir.

✅ Solución
ENTRADA: harina_maíz, agua, sal, queso, aceite
SALIDA: pupusas listas

mezclar harina_maíz con agua y sal hasta formar masa
PARA cada pupusa:
    tomar una porción de masa
    aplanar la masa en un disco
    rellenar con queso
    cerrar y aplanar nuevamente
    cocinar en comal con aceite a fuego medio por 3 min cada lado
FIN PARA
DEVOLVER pupusas listas

1.2 — Encontrar el máximo (intermedio)

Dada una lista de números enteros, escribí pseudocódigo para encontrar el máximo sin usar la función max().

💡 Pista

Suponé que el primer elemento es el máximo. Recorrelo y actualizá si encontrás algo mayor.

✅ Solución
ENTRADA: lista de enteros L con |L| ≥ 1
SALIDA: el máximo elemento

máximo ← L[0]
PARA i DESDE 1 HASTA |L| - 1:
    SI L[i] > máximo:
        máximo ← L[i]
DEVOLVER máximo

Complejidad: O(n)O(n). Es óptimo: tenés que mirar cada elemento al menos una vez.


Cap. 2-3 — Primer programa, variables y tipos

2.1 — Conversión de unidades (básico)

Escribí un programa que pida grados Celsius y muestre la conversión a Fahrenheit. Fórmula: F=C9/5+32F = C \cdot 9/5 + 32.

✅ Solución
celsius = float(input("Temperatura en °C: "))
fahrenheit = celsius * 9/5 + 32
print(f"{celsius}°C = {fahrenheit}°F")

Trampa: si usás int() en lugar de float(), el usuario no puede escribir 36.5.

2.2 — Tipos sospechosos (básico)

¿Qué imprime cada línea? Pensá antes de correr.

print(2 + 3)
print("2" + "3")
print(2 + "3")
print(type(3 / 2))
print(type(3 // 2))
✅ Solución
5             # int + int
23            # concatenación de strings
TypeError     # mezclar tipos sin conversión explícita
<class 'float'>  # / siempre devuelve float en Python 3
<class 'int'>    # // es división entera

Cap. 4 — Operadores

4.1 — Edad en días (básico)

Pedí al usuario su edad en años y mostrá su edad en días, sin considerar bisiestos.

✅ Solución
años = int(input("Edad en años: "))
días = años * 365
print(f"Tenés aproximadamente {días} días.")

4.2 — Operadores lógicos (intermedio)

¿Cuál es el resultado de cada expresión?

print(True and False or True)
print(not (True and False))
print(5 > 3 and 2 > 4)
print((5 > 3) or (2 > 4) and False)
💡 Pista

Recordá precedencia: not > and > or. and se evalúa antes que or.

✅ Solución
True   # (True and False) or True = False or True = True
True   # not False
False  # 5>3 es True, 2>4 es False, True and False = False
True   # (5>3) or ((2>4) and False) = True or False = True

Cap. 5 — Condicionales

5.1 — Descuento de pupusas (básico)

Pedí una cantidad de pupusas. Si son menos de 10, costo = cantidad * 0.50. Si son entre 10 y 19, costo = cantidad * 0.45. Si son 20 o más, costo = cantidad * 0.40. Mostrá el costo total.

✅ Solución
cantidad = int(input("¿Cuántas pupusas? "))
if cantidad < 10:
    precio = 0.50
elif cantidad < 20:
    precio = 0.45
else:
    precio = 0.40
total = cantidad * precio
print(f"Total: ${total:.2f}")

5.2 — Año bisiesto (intermedio)

Un año es bisiesto si es divisible por 4, excepto los divisibles por 100, excepto los divisibles por 400.

💡 Pista

2000 es bisiesto. 1900 no. 2024 sí.

✅ Solución
def es_bisiesto(año: int) -> bool:
    if año % 400 == 0:
        return True
    if año % 100 == 0:
        return False
    return año % 4 == 0

Una sola línea: return año % 400 == 0 or (año % 4 == 0 and año % 100 != 0).


Cap. 6 — Bucles

6.1 — Tabla de multiplicar (básico)

Pedí un número nn y mostrá su tabla de multiplicar del 1 al 10.

✅ Solución
n = int(input("Número: "))
for i in range(1, 11):
    print(f"{n} x {i} = {n * i}")

6.2 — Suma de pares (intermedio)

Calculá la suma de todos los pares entre 1 y nn, sin usar sum().

✅ Solución
n = int(input("Hasta qué número: "))
suma = 0
for i in range(2, n + 1, 2):
    suma += i
print(suma)

Bonus: la fórmula cerrada es n(n/2+1)/2n(n/2 + 1)/2 para nn par.

6.3 — FizzBuzz (intermedio)

Para ii de 1 a 100: si es múltiplo de 3 imprimí "Fizz", si es de 5 imprimí "Buzz", si es de ambos "FizzBuzz", sino el número.

✅ Solución
for i in range(1, 101):
    if i % 15 == 0:
        print("FizzBuzz")
    elif i % 3 == 0:
        print("Fizz")
    elif i % 5 == 0:
        print("Buzz")
    else:
        print(i)

Trampa: chequear % 15 (o % 3 == 0 and % 5 == 0) primero, no al final, sino la rama de FizzBuzz nunca se alcanza.


Cap. 7 — Funciones

7.1 — Promedio (básico)

Definí una función promedio(lista) que devuelva el promedio de los números de una lista. Manejá el caso de lista vacía.

✅ Solución
def promedio(lista):
    if not lista:
        return 0
    return sum(lista) / len(lista)

Decisión de diseño: ¿devolver 0 o lanzar error en lista vacía? Depende del dominio. Para promedios de notas, error es mejor (un alumno sin notas no tiene promedio 0). Para suavizado, 0 está bien.

7.2 — Factorial recursivo (intermedio)

Implementá n!n! recursivamente. Caso base: 0!=10! = 1.

✅ Solución
def factorial(n: int) -> int:
    if n < 0:
        raise ValueError("factorial no definido para negativos")
    if n == 0 or n == 1:
        return 1
    return n * factorial(n - 1)

Trampa: sin caso base n==0n == 0, recursión infinita.

7.3 — Es primo (avanzado)

Función que indique si un número es primo. Optimizala: solo necesitás chequear divisores hasta n\sqrt{n}.

✅ Solución
def es_primo(n: int) -> bool:
    if n < 2:
        return False
    if n < 4:
        return True            # 2 y 3 son primos
    if n % 2 == 0:
        return False           # pares ≥ 4 no son primos
    i = 3
    while i * i <= n:
        if n % i == 0:
            return False
        i += 2                 # solo impares
    return True

Por qué n\sqrt{n}: si n=abn = a \cdot b con a,b>1a, b > 1, entonces ana \leq \sqrt{n} o bnb \leq \sqrt{n}. Con uno de los dos alcanza.


Reto integrador

R.1 — Sistema de pedidos de pupusería (proyecto)

Implementá un sistema interactivo:

  1. Mostrá un menú de 5 productos con precios.
  2. El usuario elige por número y cantidad.
  3. Cuando termina (elige opción "salir"), mostrá la cuenta total con IVA del 13 %.
  4. Aplicá descuento del 10 % si el subtotal supera los $20.
💡 Pista de arquitectura
  • Una función por responsabilidad: mostrar_menu(), pedir_producto(), calcular_total(items, iva, descuento).
  • Usá diccionarios para el carrito: {producto: cantidad}.
  • El while True con break es válido para el bucle del menú.
✅ Solución (estructura)
MENU = {
    1: ("Pupusa de queso", 0.50),
    2: ("Pupusa revuelta", 0.60),
    3: ("Curtido", 0.25),
    4: ("Refresco de tamarindo", 1.00),
    5: ("Frijoles licuados", 0.75),
}
IVA = 0.13
UMBRAL_DESCUENTO = 20.0
DESCUENTO = 0.10


def mostrar_menu():
    print("\n--- Menú ---")
    for i, (nombre, precio) in MENU.items():
        print(f"  {i}. {nombre} ........ ${precio:.2f}")
    print("  0. Terminar pedido")


def calcular_total(carrito):
    subtotal = sum(MENU[id][1] * cant for id, cant in carrito.items())
    descuento = subtotal * DESCUENTO if subtotal > UMBRAL_DESCUENTO else 0
    base = subtotal - descuento
    iva = base * IVA
    return subtotal, descuento, iva, base + iva


def main():
    carrito = {}
    while True:
        mostrar_menu()
        op = int(input("Opción: "))
        if op == 0:
            break
        if op not in MENU:
            print("Opción inválida.")
            continue
        cant = int(input("Cantidad: "))
        carrito[op] = carrito.get(op, 0) + cant

    if not carrito:
        print("Carrito vacío.")
        return

    sub, desc, iva, total = calcular_total(carrito)
    print(f"\nSubtotal: ${sub:.2f}")
    if desc > 0: print(f"Descuento: -${desc:.2f}")
    print(f"IVA (13 %): ${iva:.2f}")
    print(f"TOTAL: ${total:.2f}")


main()

Bonus: convertí cada función en testeable con pytest. calcular_total({1: 5}) debería devolver subtotal $2.50, descuento 0, etc.


Si encontrás un ejercicio mal o querés sugerir uno, escribime.