Counting Sundays
El 1 de enero de 1900 fue lunes.
¿Cuántos domingos cayeron en el primer día del mes
durante el siglo XX (1 ene 1901 al 31 dic 2000)?
1 Entendiendo el Calendario
Para resolver este problema, necesitamos entender cómo funcionan los días de la semana y los años bisiestos.
Los días de la semana son cíclicos
Los días de la semana se repiten cada 7 días. Podemos representarlos con números:
0
1
2
3
4
5
6
Si hoy es lunes (1), en 31 días será: (1 + 31) % 7 = 32 % 7 = 4 (jueves)
Días en cada mes
Regla de los Años Bisiestos
Un año es bisiesto si:
- Es divisible por 4, Y
- NO es divisible por 100, A MENOS QUE
- Sea divisible por 400
| Año | ÷4 | ÷100 | ÷400 | ¿Bisiesto? |
|---|---|---|---|---|
| 1900 | ✓ | ✓ | ✗ | NO |
| 1904 | ✓ | ✗ | ✗ | SÍ |
| 2000 | ✓ | ✓ | ✓ | SÍ |
| 2100 | ✓ | ✓ | ✗ | NO |
El Algoritmo
- Sabemos que el 1 de enero de 1900 es lunes
- Avanzamos mes a mes, sumando los días de cada mes
- El día de la semana es
(días_totales) % 7 - Cada vez que el día 1 de un mes sea domingo (0), contamos
- Solo contamos desde 1901 hasta 2000
Ejemplo: Primeros meses de 1901
1 ene 1900 = lunes. ¿Qué día es el 1 de enero de 1901?
1900 tiene 365 días (no bisiesto)
365 % 7 = 1
Lunes + 1 = Martes
→ 1 enero 1901 fue martes
2 Simulación Manual
Simulamos el calendario día a día (o mes a mes), manteniendo el registro del día de la semana usando aritmética modular.
Función para años bisiestos
# Traducción directa de las reglas
def is_leap(year):
if year % 400 == 0: return True
if year % 100 == 0: return False
if year % 4 == 0: return True
return False
Nota: El orden importa. Primero comprobamos 400, luego 100, luego 4.
¿Por qué funciona el módulo 7?
Los días de la semana son cíclicos con período 7. Si sumamos días y aplicamos módulo 7, obtenemos el día de la semana:
# Lunes + 31 días
(1 + 31) % 7 = 4 ← Jueves
# Jueves + 28 días
(4 + 28) % 7 = 4 ← Jueves
28 días = exactamente 4 semanas, así que el día no cambia.
100 años × 12 meses = 1200 iteraciones
Solo guardamos el día actual
3 Usando el Módulo datetime
Python tiene un módulo datetime que maneja todas las complejidades del calendario.
¿Por qué reinventar la rueda?
El módulo datetime
datetime es parte de la biblioteca estándar de Python.
Maneja fechas, horas, zonas horarias, y más.
# Crear una fecha
from datetime import date
d = date(2000, 1, 1) # 1 enero 2000
# Obtener el día de la semana
d.weekday() # 0=Lunes ... 6=Domingo
d.isoweekday() # 1=Lunes ... 7=Domingo
weekday() vs isoweekday()
| Día | weekday() | isoweekday() |
|---|---|---|
| Lunes | 0 | 1 |
| Martes | 1 | 2 |
| Miércoles | 2 | 3 |
| Jueves | 3 | 4 |
| Viernes | 4 | 5 |
| Sábado | 5 | 6 |
| Domingo | 6 | 7 |
weekday() es 0-indexed (como los arrays).
isoweekday() sigue el estándar ISO 8601.
¿Simulación manual o datetime?
Simulación manual
- Entender cómo funcionan los calendarios
- Entrevistas técnicas
- Cuando no hay biblioteca disponible
datetime (recomendado)
- Código de producción
- Menos bugs (ya está probado)
- Más legible y mantenible