5 samedis, 5 dimanches et 5 lundis
Article mis en ligne le 17 février 2023

par Geneviève BOUVART

Défi PV152-1-
« À quand la prochaine année avec cinq samedis, cinq dimanches et cinq lundis dans le même mois ? »

Solution arithmétique
Un mois comprend 5 samedis, 5 dimanches et 5 lundis si et seulement s’il commence par un samedi et comporte 31 jours.
Lors d’une année non bissextile le premier de chaque mois occupe les rangs 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335.
Ce qui donne modulo 7 : 1, 4, 4, 0, 2, 5, 0, 3, 6, 1, 4, 6 que l’on peut noter p1, …, p12
Notons le rang des jours de la semaine j1, … j7. Ainsi le lundi est représenté par j1=1.
Si jk est le premier jour de l’année, les « samedis 1 » seront positionnés par pi=7-jk.
Par exemple en 2023 le premier jour de l’année était un dimanche soit jk=7. Alors pi=0.
Or p4=0 et p7=0 Le septième mois de l’année, soit le mois de juillet comportera 5 samedis, 5 dimanches et 5 lundis. On exclut le mois d’avril qui ne comporte que 30 jours.
Solutions obtenues par algorithme

Résultats
2025 [’Mars’]
2026 [’Aout’]
2027 [’Mai’]
2028 [’Janvier’, ’Juillet’]
2029 [’Décembre’]
2031 [’Mars’]
2032 [’Mai’]
2033 [’Janvier’, ’Octobre’]
2035 [’Décembre’]
2036 [’Mars’]
2037 [’Aout’]
2038 [’Mai’]
2039 [’Janvier’, ’Octobre’]
2042 [’Mars’]
2043 [’Aout’]
2044 [’Octobre’]
2046 [’Décembre’]
2048 [’Aout’]
2049 [’Mai’]
2050 [’Janvier’, ’Octobre’]
2053 [’Mars’]
2054 [’Aout’]
2055 [’Mai’]
2056 [’Janvier’, ’Juillet’]
2057 [’Décembre’]
2059 [’Mars’]

2060 [’Mai’]
2061 [’Janvier’, ’Octobre’]
2063 [’Décembre’]
2064 [’Mars’]
2065 [’Aout’]
2066 [’Mai’]
2067 [’Janvier’, ’Octobre’]
2070 [’Mars’]
2071 [’Aout’]
2072 [’Octobre’]
2074 [’Décembre’]
2076 [’Aout’]
2077 [’Mai’]
2078 [’Janvier’, ’Octobre’]
2081 [’Mars’]
2082 [’Aout’]
2083 [’Mai’]
2084 [’Janvier’, ’Juillet’]
2085 [’Décembre’]
2087 [’Mars’]
2088 [’Mai’]
2089 [’Janvier’, ’Octobre’]
2091 [’Décembre’]
2092 [’Mars’]
2093 [’Aout’]
2094 [’Mai’]
2095 [’Janvier’, ’Octobre’]
2098 [’Mars’]
2099 [’Aout’]
2100 [’Mai’]
2101 [’Janvier’, ’Octobre’]
2103 [’Décembre’]
2104 [’Mars’]
2105 [’Aout’]
2106 [’Mai’]
2107 [’Janvier’, ’Octobre’]
2110 [’Mars’]
2111 [’Aout’]
2112 [’Octobre’]
2114 [’Décembre’]
2116 [’Aout’]
2117 [’Mai’]
2118 [’Janvier’, ’Octobre’]
2121 [’Mars’]
2122 [’Aout’]
2123 [’Mai’]

Une première proposition
# !/usr/bin/env python3
# -*- coding : utf-8 -*-
"""
Created on Thu Feb 16 10:29:52 2023

@author : gilles
"""

def bissextile(n) :
"""
Fonction bissextile

Paramètres
----------
n : entier
numéro de l’année

Renvoi
-------
booléen
indique si l’année est bissextile ou non
"""
return n%4 == 0 and (n % 100 !=0 or n%400==0)

def jour_suivant(m,an,jseed) :
"""
Fonction jour_suivant

Paramètres
----------
mois : entier
numéro du mois de l’année précédente
an : entier
numéro de l’année précédente
jseed : entier
numéro du jour de la semaine précédent le premier du mois m

Returns
------
entier
numéro du jour de la semaine du dernier jour du mois m

"""
moisn=1:31,2:28,3:31,4:30,5:31,6:30,7:31,8:31,9:30,10:31,11:30,12:31 # nombre de jours par mois
if m==2 and bissextile(an) :
nj=29
else :
nj=moisn[m]
return (jseed+nj)%7

def sdl5(m,jseed) :
"""
Fonction sdl5

Paramètres
----------
mois : entier
numéro du mois de l’année
jseed : entier
numéro du jour de la semaine précédent le premier du mois mois

Renvoi
-------
booléen
Vrai si le mois m comporte 5 samedis, 5 dimanches et 5 lundis
"""
moisn=1:31,2:28,3:31,4:30,5:31,6:30,7:31,8:31,9:30,10:31,11:30,12:31 # nombre de jours par mois
return jseed==4 and moisn[m]==31

def genere(jseed,m,annee,duree) :
"""
Fonction genere

Paramètres
----------
mois : entier
numéro du mois de l’année précédente
annee : entier
numéro de l’année précédente
jseed : entier
numéro du jour de la semaine du premier du mois m
duree : entier
nombre d’années à étudier depuis l’année an

Renvoi
-------
res : dictionnaire
les clés sont les années et les valeurs sont les tableaux des mois qui comportent 5 samedis, 5 dimanches et 5 lundis

"""
res={}
jour=jseed-1
nommois=1 :"janvier", 2 :"février", 3 :"mars", 4 :"avril", 5 :"mai", 6 :"juin", 7 :"juillet", 8 :"août", 9 :"septembre", 10 : "octobre", 11 :"novembre", 12 :"décembre" # noms des mois de l’année
for an in range(annee,annee+duree) :
while m < 13 :
if sdl5(m,jour) :
if an in res.keys() :
res[an].append(nommois[m])
else :
res[an]=[nommois[m]]
jour=jour_suivant(m, an, jour)
m += 1
m=1
return res

# Le 1 er janvier 2023 est un dimanche, donc, pour avoir les mois qui comptent 5 samedis, 5 dimanches et 5 lundis sur 20 ans on saisit :

print(genere(6, 1, 2023, 20))

Une deuxième proposition

Programme Python « les cinq samedis, dimanches et lundis » dans un mois

def bissextile(a) :
"""
Fonction bissextile(a : entier ;booléen)
renvoie Vrai si a est une année bissextile, Faux sinon
"""
return a%4==0 and (a%100 !=0 or a%400==0)

def nb_jourstotal(a) :
"""Fonction nbjourstotal(a : entier)
renvoie le nombre de jours total depuis le premier janvier"""
jourstotMois=[1]
if bissextile(a) :
for i in range(12) :
jourstotMois.append(joursMoisb[i]+jourstotMois[i])

else :
for i in range(12) :
jourstotMois.append(joursMois[i]+jourstotMois[i])
return jourstotMois

def rang_pj_mois(L) :
""" Fonction_rang_premier_jour_mois(L:liste) renvoie le rang du premier jour du mois qui a le même nom que le nom du premier janvier
Le 1 janvier est au rang 1 ; le 1 février est au rang 31 +1=32, ce qui donne 4 modulo7"""
essai=[]
for i in range(12) :
essai.append(L[i]%7)
return essai

def rang_mois_recherche(k,j,rang) :
"""Fonction numérique rang_mois_recherche(k:entier,j:entier,rang:liste)
Renvoie la liste des mois qui correspondent au rang recherché pour une année donnée.
Si k est le numéro du jour du premier jour de l’année, les « samedis 1 (j) » seront positionnés par j+1-k."""

L=[]
for i in range(12) :
if rang[i]==j+1-k and joursMois[i]==31 :
L.append(Mois[i])
return L

def Calendrier(n) :
"""Fonction numérique(n:entier)
Renvoie un dictionnaire avec les années et les mois correspondants qui comportent 5 samedis, 5 dimanches et 5 lundis"""
calendrier={}
a=2023
j=7
for i in range(n) :
j= (nb_jourstotal(a)[12]+j-1)%7
a=a+1
calendrier[a]=rang_mois_recherche(j,6,rang_pj_mois(nb_jourstotal(a)))
return calendrier

# Programme principal.
Mois=[’Janvier’, ’Février’, ’Mars’, ’Avril’, ’Mai’, ’Juin’, ’Juillet’, ’Aout’, ’Septembre’, ’Octobre’,’ Novembre’, ’Décembre’]
joursMois=[31,28,31,30,31,30,31,31,30,31,30,31]
joursMoisb=[31,29,31,30,31,30,31,31,30,31,30,31]
semaine=["Lundi",’Mardi’,’Mercredi’, ’Jeudi’,’Vendredi’, ’Samedi’, ’Dimanche’]

"""Désherbage de l’affichage avec la suppression des années ne comportant pas de mois à 5 samedis, 5 dimanches et 5 lundis"""
dcalendrier=k : v for k, v in Calendrier(100).items() if v !=[]

for k in dcalendrier :
print(k,dcalendrier[k])

qrcode:https://apmeplorraine.fr/spip.php?article1034