20 ejercicios avanzados de Python resueltos paso a paso

20 ejercicios avanzados de Python resueltos paso a paso: listas, diccionarios, matrices, búsqueda, ordenamiento, validaciones y pequeños sistemas prácticos.


Después de dominar variables, condicionales, ciclos, listas y funciones, el siguiente paso es aprender a combinar esos conceptos para resolver problemas más completos.

Estos 20 ejercicios avanzados de Python resueltos paso a paso están pensados para practicar procesamiento de datos, estructuras anidadas, búsquedas, ordenamientos, matrices, validaciones y pequeños sistemas sin introducir todavía conceptos de programación orientada a objetos como herencia.

Si necesitás repasar antes, podés comenzar por 20 ejercicios resueltos de Python para principiantes, 20 ejercicios de listas en Python o Funciones en Python.

Índice de ejercicios

  1. Contar la frecuencia de palabras
  2. Normalizar una lista de nombres
  3. Agrupar alumnos por curso
  4. Ordenar registros por más de un criterio
  5. Eliminar duplicados conservando el orden
  6. Comparar dos listas y detectar cambios
  7. Generar estadísticas de una lista
  8. Unir dos listas por identificador
  9. Calcular totales de una matriz
  10. Trasponer una matriz
  11. Validar una contraseña con varias reglas
  12. Cifrado César
  13. Detectar palíndromos en frases
  14. Validar paréntesis balanceados
  15. Buscar varias coincidencias con búsqueda binaria
  16. Ordenar registros sin usar sort()
  17. Crear un sistema de inventario
  18. Calcular el total de un carrito con descuentos
  19. Procesar datos separados por comas
  20. Mini proyecto: gestor de productos

1. Contar la frecuencia de palabras

Enunciado: Contar cuántas veces aparece cada palabra en un texto ignorando mayúsculas y signos simples.

texto = "Python es simple. Python es potente."

texto = texto.lower().replace(".", "")
palabras = texto.split()

frecuencias = {}

for palabra in palabras:
    if palabra in frecuencias:
        frecuencias[palabra] += 1
    else:
        frecuencias[palabra] = 1

print(frecuencias)

lower() normaliza el texto y split() lo divide en palabras. El diccionario guarda cada palabra como clave y su cantidad de apariciones como valor.

2. Normalizar una lista de nombres

Enunciado: Quitar espacios sobrantes y dejar todos los nombres con formato consistente.

nombres = ["  ana", "LUIS ", "  mArTa  "]
normalizados = []

for nombre in nombres:
    limpio = nombre.strip().title()
    normalizados.append(limpio)

print(normalizados)

strip() elimina espacios al principio y al final. title() devuelve una nueva cadena con formato de título.

3. Agrupar alumnos por curso

Enunciado: Crear un diccionario donde cada curso contenga su lista de alumnos.

alumnos = [
    {"nombre": "Ana", "curso": "A"},
    {"nombre": "Luis", "curso": "B"},
    {"nombre": "Marta", "curso": "A"}
]

grupos = {}

for alumno in alumnos:
    curso = alumno["curso"]

    if curso not in grupos:
        grupos[curso] = []

    grupos[curso].append(alumno["nombre"])

print(grupos)

Este patrón permite transformar una lista plana en información agrupada. Es muy útil para reportes y resúmenes.

4. Ordenar registros por más de un criterio

Enunciado: Ordenar alumnos por nota descendente y luego por nombre.

alumnos = [
    {"nombre": "Luis", "nota": 8},
    {"nombre": "Ana", "nota": 9},
    {"nombre": "Carlos", "nota": 8}
]

def criterio(alumno):
    return (-alumno["nota"], alumno["nombre"])

ordenados = sorted(alumnos, key=criterio)

for alumno in ordenados:
    print(alumno)

sorted() devuelve una nueva lista. La función usada en key define el criterio de ordenamiento sin modificar la lista original.

5. Eliminar duplicados conservando el orden

Enunciado: Quitar valores repetidos sin alterar el orden de aparición.

datos = [4, 2, 4, 7, 2, 9, 7]
unicos = []

for dato in datos:
    if dato not in unicos:
        unicos.append(dato)

print(unicos)

A diferencia de convertir directamente a set, esta solución hace explícito que queremos conservar el orden original.

6. Comparar dos listas y detectar cambios

Enunciado: Obtener elementos agregados y eliminados entre dos versiones.

anterior = [1, 2, 3, 4]
actual = [2, 3, 4, 5]

agregados = []
eliminados = []

for elemento in actual:
    if elemento not in anterior:
        agregados.append(elemento)

for elemento in anterior:
    if elemento not in actual:
        eliminados.append(elemento)

print("Agregados:", agregados)
print("Eliminados:", eliminados)

Comparar estados anteriores y actuales aparece en sincronizaciones, formularios y procesos de actualización.

7. Generar estadísticas de una lista

Enunciado: Calcular mínimo, máximo, promedio y cantidad de valores.

numeros = [12, 7, 19, 4, 15, 10]

estadisticas = {
    "cantidad": len(numeros),
    "minimo": min(numeros),
    "maximo": max(numeros),
    "promedio": sum(numeros) / len(numeros)
}

print(estadisticas)

min(), max() y sum() permiten resolver operaciones habituales sobre colecciones numéricas.

8. Unir dos listas por identificador

Enunciado: Combinar información proveniente de dos listas relacionadas por id.

usuarios = [
    {"id": 1, "nombre": "Ana"},
    {"id": 2, "nombre": "Luis"}
]

edades = [
    {"usuario_id": 1, "edad": 28},
    {"usuario_id": 2, "edad": 34}
]

resultado = []

for usuario in usuarios:
    registro = usuario.copy()

    for dato in edades:
        if dato["usuario_id"] == usuario["id"]:
            registro["edad"] = dato["edad"]
            break

    resultado.append(registro)

print(resultado)

Este ejercicio reproduce de forma simple una operación parecida a un join: relacionamos registros mediante un identificador común.

9. Calcular totales de una matriz

Enunciado: Calcular la suma de cada fila y de cada columna.

matriz = [
    [3, 5, 2],
    [7, 1, 4],
    [6, 8, 9]
]

for fila in matriz:
    print("Total fila:", sum(fila))

cantidad_columnas = len(matriz[0])

for columna in range(cantidad_columnas):
    total = 0

    for fila in matriz:
        total += fila[columna]

    print("Total columna", columna, ":", total)

Las matrices pueden representarse como listas de listas. Para recorrer columnas necesitamos mantener fijo el índice de columna y avanzar por cada fila.

10. Trasponer una matriz

Enunciado: Convertir filas en columnas.

matriz = [
    [1, 2, 3],
    [4, 5, 6]
]

traspuesta = []

for columna in range(len(matriz[0])):
    nueva_fila = []

    for fila in matriz:
        nueva_fila.append(fila[columna])

    traspuesta.append(nueva_fila)

print(traspuesta)

La traspuesta intercambia filas por columnas. Es un buen ejercicio para practicar índices y estructuras bidimensionales.

11. Validar una contraseña con varias reglas

Enunciado: Comprobar longitud, mayúsculas, minúsculas y números.

clave = "Python2026"

tiene_mayuscula = False
tiene_minuscula = False
tiene_numero = False

for caracter in clave:
    if caracter.isupper():
        tiene_mayuscula = True
    elif caracter.islower():
        tiene_minuscula = True
    elif caracter.isdigit():
        tiene_numero = True

valida = (
    len(clave) >= 8
    and tiene_mayuscula
    and tiene_minuscula
    and tiene_numero
)

print("Contraseña válida:", valida)

El ejercicio combina recorrido de cadenas, varias condiciones y estado acumulado mediante variables booleanas.

12. Cifrado César

Enunciado: Desplazar cada letra una cantidad fija de posiciones.

texto = "hola"
desplazamiento = 3
resultado = ""

for caracter in texto:
    codigo = ord(caracter)
    nuevo_codigo = codigo + desplazamiento
    resultado += chr(nuevo_codigo)

print(resultado)

ord() devuelve el código numérico de un carácter y chr() realiza la operación inversa. Esta versión simple está pensada para practicar la lógica del desplazamiento.

13. Detectar palíndromos en frases

Enunciado: Comprobar una frase ignorando espacios y mayúsculas.

frase = "Anita lava la tina"

normalizada = frase.lower().replace(" ", "")
invertida = normalizada[::-1]

if normalizada == invertida:
    print("Es palíndromo")
else:
    print("No es palíndromo")

El slicing [::-1] crea una versión invertida de la cadena. Antes normalizamos el contenido para que la comparación sea útil.

14. Validar paréntesis balanceados

Enunciado: Comprobar si los paréntesis de una expresión están correctamente abiertos y cerrados.

expresion = "(a + b) * (c - d)"
pila = []
valida = True

for caracter in expresion:
    if caracter == "(":
        pila.append(caracter)
    elif caracter == ")":
        if len(pila) == 0:
            valida = False
            break

        pila.pop()

if len(pila) > 0:
    valida = False

print("Expresión válida:", valida)

La lista funciona como una pila: append() agrega una apertura y pop() retira la última cuando aparece un cierre.

15. Buscar varias coincidencias con búsqueda binaria

Enunciado: Encontrar todas las posiciones de un valor repetido en una lista ordenada.

numeros = [1, 2, 2, 2, 4, 7, 9]
buscado = 2

izquierda = 0
derecha = len(numeros) - 1
encontrado = -1

while izquierda <= derecha:
    medio = (izquierda + derecha) // 2

    if numeros[medio] == buscado:
        encontrado = medio
        break
    elif numeros[medio] < buscado:
        izquierda = medio + 1
    else:
        derecha = medio - 1

posiciones = []

if encontrado != -1:
    i = encontrado

    while i >= 0 and numeros[i] == buscado:
        posiciones.append(i)
        i -= 1

    i = encontrado + 1

    while i < len(numeros) and numeros[i] == buscado:
        posiciones.append(i)
        i += 1

posiciones.sort()

print(posiciones)

Primero aplicamos búsqueda binaria para encontrar una coincidencia y después recorremos hacia ambos lados para localizar las repeticiones.

16. Ordenar registros sin usar sort()

Enunciado: Implementar selección para ordenar productos por precio.

productos = [
    {"nombre": "Mouse", "precio": 30},
    {"nombre": "Teclado", "precio": 80},
    {"nombre": "Monitor", "precio": 250}
]

for i in range(len(productos)):
    menor = i

    for j in range(i + 1, len(productos)):
        if productos[j]["precio"] < productos[menor]["precio"]:
            menor = j

    productos[i], productos[menor] = productos[menor], productos[i]

print(productos)

El algoritmo de selección busca el menor elemento restante y lo coloca en su posición. Aquí adaptamos el criterio para trabajar con diccionarios.

17. Crear un sistema de inventario

Enunciado: Agregar productos, actualizar stock, buscar por código y calcular el valor total.

inventario = []

def buscar_producto(codigo):
    for producto in inventario:
        if producto["codigo"] == codigo:
            return producto

    return None

def agregar_producto(codigo, nombre, precio, stock):
    if buscar_producto(codigo) is None:
        inventario.append({
            "codigo": codigo,
            "nombre": nombre,
            "precio": precio,
            "stock": stock
        })

def actualizar_stock(codigo, cantidad):
    producto = buscar_producto(codigo)

    if producto is not None:
        producto["stock"] += cantidad

def valor_total():
    total = 0

    for producto in inventario:
        total += producto["precio"] * producto["stock"]

    return total

agregar_producto("A1", "Mouse", 25, 10)
agregar_producto("B2", "Teclado", 60, 5)
actualizar_stock("A1", 3)

print(inventario)
print("Valor total:", valor_total())

El problema combina funciones reutilizables, listas de diccionarios, búsquedas y acumuladores sin introducir programación orientada a objetos.

18. Calcular el total de un carrito con descuentos

Enunciado: Aplicar descuentos según cantidad y calcular el total final.

carrito = [
    {"producto": "Mouse", "precio": 25, "cantidad": 2},
    {"producto": "Teclado", "precio": 60, "cantidad": 5}
]

total = 0

for item in carrito:
    subtotal = item["precio"] * item["cantidad"]

    if item["cantidad"] >= 5:
        subtotal *= 0.9

    total += subtotal

print("Total:", round(total, 2))

Este tipo de ejercicio combina reglas de negocio, cálculos y estructuras de datos. round() permite limitar la cantidad de decimales del resultado.

19. Procesar datos separados por comas

Enunciado: Interpretar texto con formato similar a CSV y calcular un resumen.

datos = """Ana,8
Luis,6
Marta,9
Pedro,7"""

lineas = datos.splitlines()
alumnos = []

for linea in lineas:
    partes = linea.split(",")

    alumnos.append({
        "nombre": partes[0],
        "nota": int(partes[1])
    })

total = 0

for alumno in alumnos:
    total += alumno["nota"]

promedio = total / len(alumnos)

print(alumnos)
print("Promedio:", promedio)

Antes de trabajar con archivos reales, este ejercicio permite practicar el procesamiento de información tabular usando sólo cadenas, listas y conversiones.

20. Mini proyecto: gestor de productos

Enunciado: Crear un pequeño sistema con altas, búsqueda, actualización y reportes.

productos = []

def agregar(codigo, nombre, precio, stock):
    for producto in productos:
        if producto["codigo"] == codigo:
            return False

    productos.append({
        "codigo": codigo,
        "nombre": nombre,
        "precio": precio,
        "stock": stock
    })

    return True

def buscar(codigo):
    for producto in productos:
        if producto["codigo"] == codigo:
            return producto

    return None

def cambiar_precio(codigo, nuevo_precio):
    producto = buscar(codigo)

    if producto is None:
        return False

    producto["precio"] = nuevo_precio
    return True

def productos_bajo_stock(limite):
    resultado = []

    for producto in productos:
        if producto["stock"] < limite:
            resultado.append(producto)

    return resultado

def valor_inventario():
    total = 0

    for producto in productos:
        total += producto["precio"] * producto["stock"]

    return total

agregar("P1", "Mouse", 25, 4)
agregar("P2", "Teclado", 70, 12)
agregar("P3", "Monitor", 250, 2)

cambiar_precio("P1", 30)

print("Bajo stock:", productos_bajo_stock(5))
print("Valor inventario:", valor_inventario())

El proyecto reúne funciones, validaciones, búsquedas, listas, diccionarios y cálculos. Es una buena forma de practicar cómo dividir un problema grande en operaciones pequeñas.

Qué estamos practicando

La dificultad de estos ejercicios no está en usar sintaxis especialmente rara, sino en combinar herramientas que ya conocés: funciones, listas, diccionarios, cadenas, ciclos, condiciones, búsqueda y ordenamiento.

Cuando un problema empieza a crecer, una buena estrategia es dividirlo en funciones pequeñas, evitar repetir lógica y elegir una estructura de datos que represente claramente la información.

Seguí aprendiendo Python


¿Te sirvió esta guía? ☕

Si este contenido te ayudó a aprender Python, podés apoyar a Club Programador. Cada aporte ayuda a mantener el sitio online y a seguir publicando material gratuito.

🇦🇷 Apoyar desde Argentina

☕ Invitame un café con Mercado Pago

🌎 Apoyar desde otro país

☕ Apoyar con PayPal


Descubre más desde Club Programador

Suscríbete y recibe las últimas entradas en tu correo electrónico.

Deja un comentario

Descubre más desde Club Programador

Suscríbete ahora para seguir leyendo y obtener acceso al archivo completo.

Seguir leyendo