← Euler Lab
#019

Contando Domingos

Cargando Python...

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)?

Aritmética modular Años bisiestos datetime

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:

Dom
0
Lun
1
Mar
2
Mié
3
Jue
4
Vie
5
Sáb
6

Si hoy es lunes (1), en 31 días será: (1 + 31) % 7 = 32 % 7 = 4 (jueves)

Días en cada mes

Enero
31
Febrero
28/29
Marzo
31
Abril
30
Mayo
31
Junio
30
Julio
31
Agosto
31
Septiembre
30
Octubre
31
Noviembre
30
Diciembre
31

Regla de los Años Bisiestos

Un año es bisiesto si:

  1. Es divisible por 4, Y
  2. NO es divisible por 100, A MENOS QUE
  3. Sea divisible por 400
Año ÷4 ÷100 ÷400 ¿Bisiesto?
1900 NO
1904
2000
2100 NO

El Algoritmo

  1. Sabemos que el 1 de enero de 1900 es lunes
  2. Avanzamos mes a mes, sumando los días de cada mes
  3. El día de la semana es (días_totales) % 7
  4. Cada vez que el día 1 de un mes sea domingo (0), contamos
  5. 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

Domingos en día 1 (1901-2000)
171
Meses revisados
1200

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.

Python — Simulación mes a mes
// Output aparecerá aquí

¿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.

Complejidad temporal
O(años × 12)

100 años × 12 meses = 1200 iteraciones

Complejidad espacial
O(1)

Solo guardamos el día actual

Aritmética modular Simulación Años bisiestos

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

Python — Con datetime (3 líneas)
// Output aparecerá aquí

weekday() vs isoweekday()

Día weekday() isoweekday()
Lunes01
Martes12
Miércoles23
Jueves34
Viernes45
Sábado56
Domingo67

weekday() es 0-indexed (como los arrays). isoweekday() sigue el estándar ISO 8601.

Python — Operaciones útiles con datetime
// Output aparecerá aquí

¿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
datetime.date weekday() / isoweekday() timedelta strftime (formateo)