IDS Guía de estudio

Semana 6 · Evaluación de medio ciclo

Repaso y Examen Parcial

Semana de examen. Aquí tienes un plan de estudio de 5 días, los 10 errores más comunes, un simulacro teórico de 15 preguntas y un simulacro práctico de 90 minutos con problemas que integran las semanas 1 a 5.

Pregunta orientadora¿Puedo combinar algoritmos, decisiones, bucles, funciones y listas para resolver un problema nuevo, sin ayuda y con tiempo limitado?

Lecturas
Repaso PCC 1–8, 11.1 · BOU 1–4
Proyecto
Al día con la Fase 3
Evaluación
Examen Parcial (esta semana)

Cómo usar esta semana

No hay contenido nuevo: esta semana es el Examen Parcial (teórico-práctico, individual, presencial en laboratorio, sin IA). El temario exacto lo confirma el docente en Moodle; lo razonable es que integre las semanas 1 a 5.

5 días antesHaz el simulacro teórico sin apuntes. Anota qué semanas fallaste.
3 días antesRepasa solo esas semanas: sus trazas y sus listas “puedo…”.
2 días antesResuelve el simulacro práctico con reloj: 90 minutos.
El día antesRelee los errores más comunes y duerme. No aprendas nada nuevo.

Mapa de repaso

En palabras simples

El Parcial no pregunta temas sueltos: pregunta combinaciones. Una lista (S5) que se recorre con un bucle (S3), dentro de una función (S4), con decisiones (S2) que siguen un algoritmo (S1).

Mapa de repaso de las semanas 1 a 5: algoritmos y Git, variables y condicionales, bucles, funciones y listas; cada tema se apoya en el anterior.
Cada semana se apoya en la anterior.
SemanaLo indispensableRepasa aquí
1algoritmos precisos, diagramas, estados de Git, add vs commit vs pushtrazas S1
2/ // % **, tipos, 0.1 + 0.2, orden de elif, fronterastrazas S2
3range, acumulador/contador/bandera, break/continue, bucles infinitostrazas S3
4return vs print, parámetros, ámbito, recursión, asserttrazas S4
5índices y slicing, alias, tuplas, búsqueda lineal, Bubble/Insertion Sorttrazas S5

Los 10 errores más comunes

Cada uno aparece en algún ejercicio o auditoría de las semanas 1 a 5. Si puedes explicar por qué cada línea de la izquierda está mal, vas bien.

#MalPor quéBien
1if total = 100:= asigna; en una condición se comparaif total == 100:
2if m > 100: … elif m > 500:la segunda rama es inalcanzabledel tramo más alto al más bajo
3> 50 cuando la regla dice “desde 50”la frontera queda fuera>= 50
4cantidad = input(...) y luego cantidad * 2input devuelve textoint(input(...))
5for m in ventas: total = 0; total += mel acumulador se reinicia en cada vueltatotal = 0 antes del bucle
6range(1, 12) para 12 mesesel fin no se incluye: 11 vueltasrange(1, 13)
7while saldo > 0: sin cambiar saldobucle infinitoactualizar la variable de la condición
8función que hace print(x) y se usa como valordevuelve Nonereturn x
9copia = listaes un alias, no una copiacopia = lista[:]
10borrar de una lista mientras se recorrese salta elementosconstruir una lista nueva

Simulacro teórico (15 preguntas)

Hazlo sin apuntes y sin ejecutar nada. Al final, cuenta cuántas acertaste por semana.

(S1) ¿Qué instrucción NO es válida en un algoritmo?

“Tarda mucho” es ambiguo. Un algoritmo exige pasos precisos.

(S1) Editaste app.py y ejecutaste git commit -m "x" sin add. ¿Qué pasa?

El commit guarda solo lo que está en el área de preparación.

(S2) ¿Cuánto vale 17 // 5 + 17 % 5?

3 + 2 = 5.

(S2) ¿Qué imprime?

x = 7
if x > 5:
    print("A")
if x > 3:
    print("B")
else:
    print("C")

Son dos if independientes (no una cadena elif): se evalúan los dos.

(S2) round(0.1 + 0.2, 2) == 0.3 vale…

Sin redondear sería False; redondeado a 2 decimales ya coincide.

(S3) ¿Qué imprime?

n = 0
for i in range(10, 0, -3):
    n += 1
print(n)

Toma 10, 7, 4, 1: cuatro vueltas.

(S3) ¿Qué imprime?

for n in [3, 8, 2, 9]:
    if n > 5:
        break
    print(n, end=" ")

Al llegar a 8, break termina todo el bucle.

(S3) ¿Qué patrón responde “¿hubo al menos una devolución?”

Una variable booleana que se enciende cuando ocurre algo.

(S4) ¿Qué vale r?

def f(a, b=10):
    return a - b
r = f(b=3, a=20)

Con argumentos nombrados el orden no importa: 20 − 3.

(S4) ¿Qué imprime?

total = 5
def sumar():
    total = 100
sumar()
print(total)

La asignación dentro crea una variable local.

(S4) ¿Qué le falta a una recursión que termina en RecursionError?

Cada llamada debe acercarse al caso base.

(S5) Con v = [5, 10, 15, 20, 25], ¿qué es v[-3:-1]?

Desde la posición −3 (15) hasta antes de −1 (25).

(S5) ¿Qué imprime?

a = [1, 2]
b = a
b.append(3)
print(len(a))

b es un alias de a.

(S5) ¿Cuántas comparaciones hace Bubble Sort (sin bandera) sobre 6 elementos?

n(n − 1)/2 = 6 × 5 / 2 = 15.

(S5) ¿Con qué datos Insertion Sort hace menos trabajo?

Cada elemento se compara una vez y se queda en su lugar.

Simulacro práctico (90 minutos)

Tres problemas que integran varias semanas. Resuélvelos en tu computadora con reloj y sin IA. Luego compara con la solución (puedes ejecutarla y modificarla aquí).

Parte A · Traza (15 min)

def resumen(ventas, meta):
    total = 0
    dias_meta = 0
    for v in ventas:
        if v < 0:
            continue
        total += v
        if v >= meta:
            dias_meta += 1
    return total, dias_meta


t, d = resumen([120, -30, 200, 80, 200], 200)
Vueltavtotaldias_meta
1
2
3
4
5

Resultado: t = 600, d = 2. En la vuelta 2, continue salta el resto del cuerpo: nada cambia.

Parte B · Programación (75 min)

P1 · Reporte semanal (S3 + S4 + S5)

funciones + listas de tuplas · ★★★

Escribe reporte(ventas) que reciba una lista de tuplas (dia, monto) y devuelva total, promedio, mejor día y la lista de días bajo el promedio. Una lista vacía no debe causar error.

Tu programa debe cumplir estos casos de prueba:

EntradaEsperado
Semana de la S5(3600, 514.29, "sáb", ["lun", "mar", "mié", "dom"])
[](0, 0, None, [])
Pista

Primero el caso borde (lista vacía). Luego un solo recorrido para total y máximo, y una comprensión para los días bajo el promedio.

Solución
def reporte(ventas):
    """Recibe [(dia, monto)] y devuelve (total, promedio, mejor_dia, dias_bajo_promedio)."""
    if not ventas:
        return 0, 0, None, []
    total = 0
    mejor_dia, mejor_monto = ventas[0]
    for dia, monto in ventas:
        total += monto
        if monto > mejor_monto:
            mejor_dia, mejor_monto = dia, monto
    promedio = total / len(ventas)
    bajos = [dia for dia, monto in ventas if monto < promedio]
    return total, round(promedio, 2), mejor_dia, bajos


semana = [("lun", 340), ("mar", 410), ("mié", 380), ("jue", 520), ("vie", 610), ("sáb", 890), ("dom", 450)]
print(reporte(semana))
assert reporte([]) == (0, 0, None, [])
assert reporte([("lun", 100)]) == (100, 100.0, "lun", [])
(3600, 514.29, 'sáb', ['lun', 'mar', 'mié', 'dom'])

P2 · Top 3 de facturas sin sort (S5)

Insertion Sort + búsqueda lineal · ★★★

Con una lista de facturas (numero, monto): devuelve las 3 de mayor monto usando tu propio Insertion Sort (sin modificar la lista original) y escribe una búsqueda lineal por número.

Tu programa debe cumplir estos casos de prueba:

LlamadaEsperado
Top 3F-102, F-104, F-101
buscar(facturas, "F-103")2
buscar(facturas, "F-999")-1
Pista

Ordena una copia (facturas[:]) comparando el campo [1] y toma [:3].

Solución
def ordenar_por_monto_desc(facturas):
    """Insertion Sort descendente por monto (sin sort ni sorted). No modifica la original."""
    datos = facturas[:]
    for i in range(1, len(datos)):
        actual = datos[i]
        j = i - 1
        while j >= 0 and datos[j][1] < actual[1]:
            datos[j + 1] = datos[j]
            j -= 1
        datos[j + 1] = actual
    return datos


def buscar(facturas, numero):
    """Búsqueda lineal: devuelve la posición o -1."""
    for i in range(len(facturas)):
        if facturas[i][0] == numero:
            return i
    return -1


facturas = [("F-101", 45.5), ("F-102", 120.0), ("F-103", 12.75), ("F-104", 88.0)]
top = ordenar_por_monto_desc(facturas)[:3]
print("Top 3:", top)
print("F-103 está en la posición", buscar(facturas, "F-103"))
print("F-999:", buscar(facturas, "F-999"))
assert facturas[0] == ("F-101", 45.5)            # la original no cambió
Top 3: [('F-102', 120.0), ('F-104', 88.0), ('F-101', 45.5)]
F-103 está en la posición 2
F-999: -1

P3 · El parqueo de la semana 1, programado y probado (S1 + S2 + S4)

del pseudocódigo al código · ★★

Convierte el pseudocódigo del E1 de la semana 1 en la función cobro_parqueo(minutos, tiene_sello=False) y verifícala con los 6 casos de la tabla de esa semana.

Tu programa debe cumplir estos casos de prueba:

Minutos, selloEsperado
60, no$1.00
61, no$1.75
600, no$6.00
30, sí$0.00
600, sí$5.00
0, no$0.00
Pista

“Hora o fracción” es redondear hacia arriba: minutos // 60 y sumar 1 si sobra algo.

Solución
def cobro_parqueo(minutos, tiene_sello=False):
    """$1.00 la primera hora, $0.75 cada hora o fracción adicional, tope $6.00; sello descuenta $1.00 al final."""
    if minutos <= 0:
        return 0.0
    horas = minutos // 60
    if minutos % 60 != 0:
        horas += 1                                  # techo sin importar math
    cobro = 1.00 + (horas - 1) * 0.75
    if cobro > 6.00:
        cobro = 6.00
    if tiene_sello:
        cobro = max(0.0, cobro - 1.00)
    return round(cobro, 2)


casos = [(60, False, 1.00), (61, False, 1.75), (600, False, 6.00), (30, True, 0.00), (600, True, 5.00), (0, False, 0.0)]
for minutos, sello, esperado in casos:
    obtenido = cobro_parqueo(minutos, sello)
    marca = "✓" if obtenido == esperado else "✗"
    print(f"{marca} {minutos:>4} min, sello={sello!s:<5} -> ${obtenido:.2f}")
✓   60 min, sello=False -> $1.00
✓   61 min, sello=False -> $1.75
✓  600 min, sello=False -> $6.00
✓   30 min, sello=True  -> $0.00
✓  600 min, sello=True  -> $5.00
✓    0 min, sello=False -> $0.00

Imprimir ✓/✗ por caso es una forma rápida de probar sin pytest; en el examen te ayuda a revisar tu propio trabajo.

Estrategia para el día del examen

Durante el examen
  • Lee todo el examen primero (3 minutos) y empieza por lo que dominas.
  • En preguntas de “¿qué imprime?”, traza en papel con una tabla: no confíes en la intuición.
  • Antes de programar, escribe en comentarios los pasos (pseudocódigo). Ya son puntos de lógica.
  • Prueba tu código con un caso normal y con uno de frontera antes de entregar.
  • Si algo no corre, deja lo que sí funciona y explica en un comentario qué falta.
Recuerda

Es individual y sin IA. Aplica el código de honor: “Por mi honor y por mis compañeros me comprometo a no copiar para que este examen revele mi verdadero nivel de conocimientos.”