diff --git a/.gitignore b/.gitignore index db4561e..425f315 100644 --- a/.gitignore +++ b/.gitignore @@ -52,3 +52,7 @@ docs/_build/ # PyBuilder target/ + +# Custom +*/sujet/* +*.zip diff --git a/S1/TP 2/Conversion Celsius Fahrenheit.py b/S1/TP 2/Conversion Celsius Fahrenheit.py new file mode 100644 index 0000000..e372530 --- /dev/null +++ b/S1/TP 2/Conversion Celsius Fahrenheit.py @@ -0,0 +1,66 @@ +# PREUD'HOMME BONTOUX Geoffrey - PeiP 12 - 2014/2015 +# TP n°2 donné le 19/09/2014 - Conversion Celsius ↔ Fahrenheit +# http://www.fil.univ-lille1.fr/~wegrzyno/portail/Info/Doc/HTML/tp_donnees_expressions.html + +# Q1 +C = 20 + +# Q2 +F = 9/5*C+32 + +# Q3 +print("Une température de", C, "°C correspond à une température de", F, "F.") + +# Q4 +F2 = 75 +C2 = 5/9*(F2-32) +print("Une température de", F2, "F correspond à une température de", C2, "°C.") + +# Q5 +def celsius_en_fahrenheit(celsius): + """ + Convertit une température en degrés Celsius en degrés Fahrenheit. + + CU : celsius numérique + + Exemple : + + >>> celsius_en_fahrenheit(20) + 68.0 + """ + return 9/5*celsius+32 + +help(celsius_en_fahrenheit) + +print("Q5", "Une température de 21 °C correspond à une température de", \ + celsius_en_fahrenheit(21), "F.") +print("Q5", "Une température de 34 °C correspond à une température de", \ + celsius_en_fahrenheit(34), "F.") +print("Q5", "Une température de 55 °C correspond à une température de", \ + celsius_en_fahrenheit(55), "F.") + +# Q6 +def fahrenheit_en_celsius(fahrenheit): + """ + Convertit une température en degrés Fahrenheit en degrés Celsius. + + CU : fahrenheit numérique + + Exemple : + + >>> fahrenheit_en_celsius(75) + 23.88888888888889 + """ + return 5/9*(fahrenheit-32) + +# Q7 +# On fait une composition de fonction (au moins deux fois pour vérifier les +# deux sens) avec un nombre choisi arbitrairement + +nombreTest = 42 + +test = celsius_en_fahrenheit( \ + fahrenheit_en_celsius( \ + celsius_en_fahrenheit( \ + fahrenheit_en_celsius(nombreTest)))) == nombreTest +print("Q7", "Le test sur la réciprocité des fonctions a retourné :", test) diff --git a/S1/TP 2/Debut du developpement en fraction continue d un reel.py b/S1/TP 2/Debut du developpement en fraction continue d un reel.py new file mode 100644 index 0000000..a73a124 --- /dev/null +++ b/S1/TP 2/Debut du developpement en fraction continue d un reel.py @@ -0,0 +1,65 @@ +# PREUD'HOMME BONTOUX Geoffrey - PeiP 12 - 2014/2015 +# TP n°2 donné le 19/09/2014 - Début du developpement en fraction continue d’un +# réel +# http://www.fil.univ-lille1.fr/~wegrzyno/portail/Info/Doc/HTML/tp_donnees_expressions.html + +# Q1 +from math import floor + +# Q2 +def afficher_debut(x): + """ + Réalise le début du développement en fraction continue d’un nombre et + affiche les parties entières calculées. + + CU : x numérique + + Exemple : + + >>> afficher_debut(3.14159265359) + a0 = 3 + a1 = 7 + a2 = 15 + """ + # Calcul des valeurs + a0 = floor(x) + y = (x - a0) ** -1 + a1 = floor(y) + z = (y - a1) ** -1 + a2 = floor(z) + + # Affichage des valeurs + print("a0 = ", a0) + print("a1 = ", a1) + print("a2 = ", a2) + +# Q3 +from math import pi + +# Q4 +afficher_debut(pi) + +def afficher_debut_bis(x): + """ + Réalise le début du développement en fraction continue d’un nombre et + affiche une approximation de ce nombre sous la forme d'une fraction + continue. + + CU : x numérique + + Exemple : + + >>> afficher_debut_bis(3.14159265359) + 3 + 1 / (7 + 1 / 15) + """ + # Calcul des valeurs + a0 = floor(x) + y = (x - a0) ** -1 + a1 = floor(y) + z = (y - a1) ** -1 + a2 = floor(z) + + # Affichage des valeurs + print(str(a0) + " + 1 / (" + str(a1) + " + 1 / " + str(a2) + ")") + +afficher_debut_bis(pi) diff --git a/S1/TP 2/Taille d un entier en base 10.py b/S1/TP 2/Taille d un entier en base 10.py new file mode 100644 index 0000000..05b7927 --- /dev/null +++ b/S1/TP 2/Taille d un entier en base 10.py @@ -0,0 +1,50 @@ +# PREUD'HOMME BONTOUX Geoffrey - PeiP 12 - 2014/2015 +# TP n°2 donné le 19/09/2014 - Taille d'un entier en base 10 +# http://www.fil.univ-lille1.fr/~wegrzyno/portail/Info/Doc/HTML/tp_donnees_expressions.html + +# Q1 +from math import log10 + +# Q2 +from math import floor +print("Q2", "floor(3.14159265359) retourne", floor(3.14159265359)) + +# Q3 +def taille(entier): + """ + Calcule la taille décimale d’un entier positif. + + CU : entier int ≥ 0 + + Exemple : + + >>> taille(2014) + 4 + """ + return floor(log10(entier)) + 1 + +# Q4 +print("Q4", "taille(2**100) retourne", taille(2**100)) + +# Q5 +# Le code qui suit a été éxecuté dans l'interpréteur puis inseré ici en tant +# que commentaire pour garder le fichier valide car il provoque des erreurs + +# >>> taille(-2014) +# Traceback (most recent call last): +# File "", line 1, in +# File "", line 12, in taille +# ValueError: math domain error + +# Lors de l'éxecution de ce script, Python détecte une erreur. Il affiche donc +# dans la console la liste des fonctions appelées en dernier afin de nous aider +# à voir d'où vient l'erreur. Ici, cette dernière vient de la fonction taille(), +# plus précisément de la ligne contenant l'instruction suivante : +# ```return floor(log10(entier)) + 1``` +# Le texte de l'erreur est le suivant : "ValueError: math domain error". Cela +# signifie qu'une fonction a été appelée avec un argument en dehors de son +# domaine de définition. La fonction en question est log10 (nous pouvons le +# vérifier en tapant dans l'interpréteur ```log10(-2014)```, qui est une étape +# de la fonction taille(), ce qui affiche la même erreur), qui est définie +# pour tout réel strictement positif. Or, -2014 n'en est pas un, ce qui +# déclenche l'erreur. diff --git a/S1/TP 2/Votre age en secondes.py b/S1/TP 2/Votre age en secondes.py new file mode 100644 index 0000000..ad14ec0 --- /dev/null +++ b/S1/TP 2/Votre age en secondes.py @@ -0,0 +1,122 @@ +# PREUD'HOMME BONTOUX Geoffrey - PeiP 12 - 2014/2015 +# TP n°2 donné le 19/09/2014 - Votre âge en secondes +# http://www.fil.univ-lille1.fr/~wegrzyno/portail/Info/Doc/HTML/tp_donnees_expressions.html + +# Q1 +ref_an = 1900 +ref_mois = 1 +ref_jour = 1 + +# Q2 +nbre_sec_jour = 24 * 60 * 60 + +# Q3 +nbre_sec_an = 365.2425 * nbre_sec_jour + +# Q4 +nbre_sec_mois = nbre_sec_an / 12 + +# Q5 +aujourdhui_jour = 19 +aujourdhui_mois = 9 +aujourdhui_an = 2014 + +# Q6 +nbre_an_entre_1900_et_aujourdhui = aujourdhui_an - ref_an +nbre_mois_entre_1900_et_aujourdhui = aujourdhui_mois - ref_mois +nbre_jour_entre_1900_et_aujourdhui = aujourdhui_jour - ref_jour +nbre_sec_entre_1900_et_aujourdhui = \ + nbre_an_entre_1900_et_aujourdhui * nbre_sec_an \ + + nbre_mois_entre_1900_et_aujourdhui * nbre_sec_mois \ + + nbre_jour_entre_1900_et_aujourdhui * nbre_sec_jour + +print("Q6", "Secondes entre la date de référence et aujourd’hui :", \ + nbre_sec_entre_1900_et_aujourdhui) + +# Q7 +naissance_jour = 14 +naissance_mois = 2 +naissance_an = 1997 + +nbre_an_entre_1900_et_naissance = naissance_an - ref_an +nbre_mois_entre_1900_et_naissance = naissance_mois - ref_mois +nbre_jour_entre_1900_et_naissance = naissance_jour - ref_jour +nbre_sec_entre_1900_et_naissance = \ + nbre_an_entre_1900_et_naissance * nbre_sec_an \ + + nbre_mois_entre_1900_et_naissance * nbre_sec_mois \ + + nbre_jour_entre_1900_et_naissance * nbre_sec_jour + + +# Q8 +mon_age_en_secondes = \ + nbre_sec_entre_1900_et_aujourdhui - nbre_sec_entre_1900_et_naissance +print("Q8", "Mon âge en secondes :", mon_age_en_secondes) + +# Q9 +def nbre_sec_depuis_1900(jour, mois, an): + """ + Calcule le nombre approximatif de secondes écoulées entre la date de + référence (le 1er janvier 1900) à 0h00 et la date passée en paramètre + + CU : jour entier ; 1 ≤ jour ≤ 31 ; mois entier ; 1 ≤ mois ≤ 12 ; + an entier ; an ≥ 1900 ; la date doit avant aujourd'hui + + Exemple : + + >>> nbre_sec_depuis_1900(14, 2, 1997) + 3064777290.0 + """ + nbre_jour_entre_1900_et_date = jour - ref_jour + nbre_mois_entre_1900_et_date = mois - ref_mois + nbre_an_entre_1900_et_date = an - ref_an + nbre_sec_entre_1900_et_date = \ + nbre_an_entre_1900_et_date * nbre_sec_an \ + + nbre_mois_entre_1900_et_date * nbre_sec_mois \ + + nbre_jour_entre_1900_et_date * nbre_sec_jour + return nbre_sec_entre_1900_et_date + +# Q10 +mon_age_en_secondes = \ + nbre_sec_depuis_1900(aujourdhui_jour, aujourdhui_mois, aujourdhui_an) \ + - nbre_sec_depuis_1900(naissance_jour, naissance_mois, naissance_an) +print("Q10", "Mon âge en secondes (via nbre_sec_depuis_1900) :", \ + mon_age_en_secondes) + +# Q11 +from datetime import * + +aujourdhui = date.today() + +aujourdhui_jour = aujourdhui.day +aujourdhui_mois = aujourdhui.month +aujourdhui_an = aujourdhui.year + +mon_age_en_secondes = \ + nbre_sec_depuis_1900(aujourdhui_jour, aujourdhui_mois, aujourdhui_an) \ + - nbre_sec_depuis_1900(naissance_jour, naissance_mois, naissance_an) +print("Q11", "Mon âge en secondes (via datetime) :", \ + mon_age_en_secondes) + + +# Q12 +def age_en_secondes(jour, mois, an): + """ + Calcule le nombre approximatif de secondes écoulées depuis la date passée + en paramètre. + + CU : jour entier ; 1 ≤ jour ≤ 31 ; mois entier ; 1 ≤ mois ≤ 12 ; + an entier ; an ≥ 1900 ; la date doit avant aujourd'hui + + Exemple (si nous sommes le 19/09/2014) : + + >>> age_en_secondes(14, 2, 1997) + 555308406.0 + """ + ajd = date.today() + return nbre_sec_depuis_1900(ajd.day, ajd.month, ajd.year) \ + - nbre_sec_depuis_1900(jour, mois, an) + +mon_age_en_secondes = \ + age_en_secondes(naissance_jour, naissance_mois, naissance_an) +print("Q12", "Mon âge en secondes (via age_en_secondes) :", \ + mon_age_en_secondes) diff --git a/S1/TP 3/Statistiques.md b/S1/TP 3/Statistiques.md new file mode 100644 index 0000000..2385edb --- /dev/null +++ b/S1/TP 3/Statistiques.md @@ -0,0 +1,8 @@ +#Statistiques sur le fichier date.py +##Brut : +**Caractères :** 14525 +**Lignes :** 419 + +##Commentaires : +**Caractrès :** 9881 (68%) +**Lignes :** 243 (57%) \ No newline at end of file diff --git a/S1/TP 3/date Camille demo.py b/S1/TP 3/date Camille demo.py new file mode 100644 index 0000000..4297dac --- /dev/null +++ b/S1/TP 3/date Camille demo.py @@ -0,0 +1,136 @@ +# Fonctions nécessaires au fonctionnement de afficher_calendrier() + +def est_divisible_par(a, b): + return a % b == 0 + +def est_bissextile(annee): + return est_divisible_par(annee, 4) and \ + (not est_divisible_par(annee, 100) or est_divisible_par(annee, 400)) + +def nbre_jours(m, a): + assert(type(m) is int and m in range(1, 13)), \ + "Le mois doit être un entier compris entre 1 et 12 inclus." + assert(type(a) is int and a > 1582), \ + "L'année doit être un entier supérieur à 1582." + + if m in [4, 6, 9, 11]: + return 30 + elif m == 2: + if est_bissextile(a): + return 29 + else: + return 28 + else: + return 31 + +def est_date_valide(j, m, a): + return type(j) is int and type(m) is int and type(a) is int and a > 1582 \ + and m in range(1, 13) and j in range(1, nbre_jours(m, a)+1) + +def corrige_mois(m, a): + assert(type(a) is int and a > 1582), \ + "L'année doit être un entier supérieur à 1582" + assert(type(m) is int and m in range(1, 13)), \ + "Le mois doit être un entier compris entre 1 et 12 inclus" + + liste_corrections_mois = [4, 0, 0, 3, 5, 1, 3, 6, 2, 4, 0, 2] + + if est_bissextile(a): + liste_corrections_mois[0] = 3 + liste_corrections_mois[1] = 6 + + return liste_corrections_mois[m-1] + +def num_jour(j, m, a): + assert(est_date_valide(j, m, a)), "La date n'est pas valide" + + ab = a//100 + cd = a%100 + return (cd//4 + ab//4 + cd + corrige_mois(m, a) + j + 2 + 5 * ab) % 7 + + +# REGARDER À PARTIR D'ICI + +# Voici une fonction qui affiche un calendier approximatif, +# sois sûre de la comprendre avant de t'attaquer au complet +def imprimer_mois_simple(m, a): + + # Première ligne + print("Mois", m, " Année", a) + + # Deuxième ligne + print("di lu ma me je ve sa") + + # Nombres + jour = 1 + nbre_jours_mois = nbre_jours(m, a) + while jour <= nbre_jours_mois: # On parcourt les lignes + ligne = ["", "", "", "", "", "", ""] # On remet à zéro la liste des nombres sur la ligne + for jour_semaine in range(7): # On parcours les colonnes de la ligne + ligne[jour_semaine] = jour # On met le jour + jour += 1 # On augumente jour pour le prochain + print(ligne[0], ligne[1], ligne[2], ligne[3], ligne[4], ligne[5], \ + ligne[6]) # On affiche la ligne + +# Démonstration +print("Calendrier simple (et faux)") +imprimer_mois_simple(9, 2014) + + +# Voici la fonction complète, qui affichera un calendrier complet, +# et possède tous les attributs d'une fonction +def imprimer_mois(m, a): + """ + Imprime le calendrier du mois de l'année donné. + + CU : m entier, a entier, 1 ≤ m ≤ 12, a > 1582 + + Exemple : + >>> imprimer_mois(9, 2014) + Septembre 2014 + di lu ma me je ve sa + 1 2 3 4 5 6 + 7 8 9 10 11 12 13 + 14 15 16 17 18 19 20 + 21 22 23 24 25 26 27 + 28 29 30 + """ + assert(type(a) is int and a > 1582), \ + "L'année doit être un entier supérieur à 1582" + assert(type(m) is int and m in range(1, 13)), \ + "Le mois doit être un entier compris entre 1 et 12 inclus" + + # On stocke les mois dans un tableau pour pouvoir y accéder facilement + liste_mois = ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", \ + "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"] + + # Première ligne + print(liste_mois[m-1], a) + + # Deuxième ligne + print("di lu ma me je ve sa") + + # Nombres + jour = 1 + jour_semaine_1er = num_jour(jour, m, a) + nbre_jours_mois = nbre_jours(m, a) + while jour <= nbre_jours_mois: # On parcourt les lignes + ligne = ["", "", "", "", "", "", ""] # On remet à zéro la liste des nombres sur la ligne + for jour_semaine in range(7): # On parcours les colonnes de la ligne + if jour == 1 and jour_semaine < jour_semaine_1er: # Si on est avant + # le premier jour du mois + ligne[jour_semaine] = " " # On met un espace + elif jour <= nbre_jours_mois: # Si on est avant la fin du mois + ligne[jour_semaine] = jour # On met le jour + jour += 1 # On augumente jour pour le prochain + print(ligne[0], ligne[1], ligne[2], ligne[3], ligne[4], ligne[5], \ + ligne[6]) # On affiche la ligne + +# Test +print("") +print("Calendrier complet") +imprimer_mois(9, 2014) + +# Comme tu as pu le remarquer, les nombres <10 font un décalage +# J'ai pas trouvé comment résoudre ça sans utiliser des trucs qu'on +# a pas vu en cours. \ No newline at end of file diff --git a/S1/TP 3/date.py b/S1/TP 3/date.py new file mode 100644 index 0000000..cf4fa13 --- /dev/null +++ b/S1/TP 3/date.py @@ -0,0 +1,418 @@ +# PREUD'HOMME BONTOUX Geoffrey - PeiP 12 - 2014/2015 +# TP n°3 donné le 26/09/2014 - Autour du calendrier +# http://www.fil.univ-lille1.fr/~wegrzyno/portail/Info/Doc/HTML/tp_conditionnelle.html + + +# [Q] Programmez une fonction nommée est_divisible_par +def est_divisible_par(a, b): + """ + Indique si a est divisible par b. + + CU : a entier, b entier + + Exemple : + + >>> est_divisible_par(2016, 4) + True + """ + # Si a est divisible par b, alors le reste de la division Euclidienne doit + # être nul + return a % b == 0 + +# [Tests] +# >>> est_divisible_par(1337, 7) +# True +# >>> est_divisible_par(997, 3) +# False + + +# [Q] Programmez une fonction nommée est_bissextile +def est_bissextile(annee): + """ + Indique si l'année a donnée est bissextile. + + CU : annee entier > 1582 + + Exemple : + >>> est_bissextile(2016) + True + """ + # Transcription des données du sujet du TP en langage Python + # L'ordre des opérations [(A⋀B)⋁C] ou [A⋀(B⋁C)] est indifférent ici + return est_divisible_par(annee, 4) and \ + (not est_divisible_par(annee, 100) or est_divisible_par(annee, 400)) + +# [Tests] +# >>> est_bissextile(2014) +# False +# >>> est_bissextile(2016) +# True +# >>> est_bissextile(2100) +# False +# >>> est_bissextile(2000) +# True + + +# [Q] Programmez une fonction nommée nbre_jours +def nbre_jours(m, a): + """ + Renvoie le nombre de jours contenus dans un mois m d’une année a donné. + + CU : m entier, a entier, 1 ≥ m ≥ 12, a > 1582 + + Exemple : + >>> nbre_jours(5, 1968) + 31 + """ + + # [Q] Complétez votre fonction nbre_jours avec assert() + assert(type(m) is int and m in range(1, 13)), \ + "Le mois doit être un entier compris entre 1 et 12 inclus." + assert(type(a) is int and a > 1582), \ + "L'année doit être un entier supérieur à 1582." + # [/Q] + + if m in [4, 6, 9, 11]: # Si le mois fait partie de ceux à 30 jours + return 30 + elif m == 2: # Sinon, si le mois est février + if est_bissextile(a): # Si l'année est bissextile + return 29 + else: + return 28 + else: # Si les conditions ci-dessus ne sont pas vérifiées, c'est forcément + # un mois de 31 jours + return 31 + + +# [Q] Testez votre fonction pour tous les mois de l’année 2014 et le mois +# de février 2016 +test = "Test nbre_jours() : " # On crée une variable pour imprimer +# une seule ligne +for test_mois in range(1, 13): # On teste pour tous les mois de 2014 + test += str(nbre_jours(test_mois, 2014)) + ", " +test += str(nbre_jours(2, 2016)) +print(test) # Enfin, on affiche + +# Test nbre_jours() : 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 29 + + +# [Q] Que donne votre fonction avec un mois m=-1 ? Est-ce normal ? + +# >>> nbre_jours(-1, 2014) +# 31 + +# On constate que la fonction retourne une valeur qui aurait pu être associée +# à certains mois valides. Le fait que la fonction retourne une valeur et ne +# déclenche pas une erreur d'elle-même est normal, car à aucun moment la +# validité des données (telles que définies dans les CU) passées en paramètres +# n'est vérifiée. Il aurait d'ailleurs été tout à fait possible que la fonction +# déclenche une erreur à cause d'une sous-fonction/procédure ne supportant pas +# qu'on lui passe certaines données interdites. +# La valeur retournée est 31, car la fonction est constituée d'une série +# d'instructions conditionelles. Dès lors qu'aucune des conditions n'est +# vérifiée, (m=-1 n'appartient pas aux mois à 30 jours ni au mois de février), +# il sera executé l'instruction "par défaut" du else, c'est à dire retourner la +# valeur 31. + + +# [Q] Quelle condition d’utilisation faut-il envisager normalement pour +# cette fonction ? + +# Il faut vérifier les valeurs passées en argument, afin de produire une erreur +# si ces dernières ne sont conformes au CU. +# De cette manière, le script s'arrêtera, et affichera un texte d'erreur +# décrivant le problème. L'avantage de faire cela au lieu de ne rien +# vérifier, est que le problème sera tout de suite montré au développeur +# utilisant la fonction, de cette manière cette dernière ne continuera pas en +# renvoiant une valeur fausse, qui faussera la partie du programme se basant +# sur celle-ci. Cette pratique permet donc d'économiser du temps de débogage. + + +# [Q] Quelle condition d’utilisation faut-il envisager normalement pour +# cette fonction ? + +# Il faut vérifier que le mois et l'année soient entier, que le mois soit +# valide, c'est à dire compris entre 1 et 12 inclus, et que la date +# soit supérieure au 15 octobre 1582 (nous arrondirerons à l'année, bien qu'il +# soit possible de vérifier si la date fournie est supérieure à la date de +# début du calendrier grégorien au jours près, il n'est pas nécessaire de +# rajouter de tels calculs en supplément pour un cas de figure qui ne sera +# probablement jamais rencontré dans le cadre de ce TP). + + +# [Q] Tapez les instructions. + +# >>> a = 1 +# >>> assert(a != 0), "a doit être différent de 0" + +# Aucun message ne s'est affiché, ni aucune erreur ne s'est produite. +# a est bien différent de 0 comme le veut la chaîne de caractère, et cette +# condition est vérifiée à l'interieur de l'instruciton assert() + +# >>> a = 0 +# >>> assert (a != 0), "a doit être différent de 0" +# Traceback (most recent call last): +# File "", line 1, in +# AssertionError: a doit être différent de 0 + +# Un message d'erreur ayant pour message "AssertionError: a doit être différent +# de 0" pour est affiché. a n'est pas différent de 0, la condition dans +# l'instruction assert() n'est pas vérifiée. + +# Nous pouvons en déduire que assert() vérifie que le test qui lui est +# donné est vrai (c'est donc un booléen), et sinon produit une erreur +# avec pour message le texte qui lui est apposé. Cette instruction pourra être +# utilisée pour vérifier les CU d'une fonction/procédure. + + +# [Q] Complétez votre fonction nbre_jours avec cette instruction + +# Voir nbre_jours(), le code ajouté pour cette question a été encadré. +# Une assertion pour l'année a été ajoutée pour garder une cohérence +# avec les CU. + + +# [Q] Trouvez différents cas de non validité d’un triplet d’entiers pour +# représenter une date. + +# Une date peut être invalide si son numéro de jour est inférieure strictement +# à 1 ou supérieur strictement au nombre de jours que peut comporter ce mois, +# ou bien si son numéro de mois est inférieur strictement à 1 ou supérieur +# strictement à 12. On considèrera comme invalide une date inférieure à 1582, +# car il est préférable de renvoyer une erreur indiquant que le programme ne +# gère pas les dates hors du calendrier grégorien plutôt que de renvoyer une +# valeur faussée, ce qui pourrait mener à d'éventuelles complications. + +# Exemples : (-14, 7, 1789), (29, 2, 1997), (31, 6, 2014), (28, 120, 1969) + + +# [Q] Programmez une fonction nommée est_date_valide +def est_date_valide(j, m, a): + """ + Indique si la date donnée appartient au calendrier grégorien. + + CU : -aucune- + + Exemple : + + >>> est_date_valide(25, 4, 1983) + True + """ + # Il n'est pas nécessaire de fournir de CU donc ne pas écrire d'instruction + # assert() car c'est le but même de la fonction. + # On vérifie les types en premier pour éviter de faire fonctionner les + # opérateurs sur d'éventuels types ne les supportant pas. + # La vérification du jour, donc l'appel de nbre_jours() est fait en dernier + # car cette dernière fonction nécessite que le mois et l'année soient + # valides. + return type(j) is int and type(m) is int and type(a) is int and a > 1582 \ + and m in range(1, 13) and j in range(1, nbre_jours(m, a)+1) + +# [Tests] +# >>> est_date_valide(25, 4, 1983) +# True +# >>> est_date_valide(-14, 7, 1789) +# False +# >>> est_date_valide(29, 2, 1997) +# False +# >>> est_date_valide(31, 6, 2014) +# False +# >>> est_date_valide(28, 120, 1969) +# False + + +# [Q] Le 15/09/2014 est un lundi. Donc, pour cette date, le numéro à +# calculer doit être 1. Vérifiez ce point. + +# Un rapide et simple calcul à l'aide du prompt de Python nous permet de le +# vérifier. On est alors sûr de la syntaxe à utiliser pour num_jour(). + +# >>> (2014%100//4 + 2014//100//4 + 2014%100 + 2 + 15 + 2 + 5 * 2014//100) % 7 +# 1 + + +# [Q] Programmez une fonction nommée corrige_mois +def corrige_mois(m, a): + """ + Renvoie la valeur corrigée du mois selon l’algorithme de Delambre. + + CU : m entier, a entier, 1 ≤ m ≤ 12, a > 1582 + + Exemple : + >>> corrige_mois(2, 2016) + 6 + """ + assert(type(a) is int and a > 1582), \ + "L'année doit être un entier supérieur à 1582" + assert(type(m) is int and m in range(1, 13)), \ + "Le mois doit être un entier compris entre 1 et 12 inclus" + # On crée un tableau de valeurs pour un accès facile aux données + liste_corrections_mois = [4, 0, 0, 3, 5, 1, 3, 6, 2, 4, 0, 2] + # Si l'année est bissextile, on y modifie uniquement les valeurs nécessaires + if est_bissextile(a): + liste_corrections_mois[0] = 3 + liste_corrections_mois[1] = 6 + # On prend dans le tableau la valeur qu'il faut + # On enlève 1 à l'index du tableau, car les mois comment à 1 + # alors que le tableau commence lui à 0 + return liste_corrections_mois[m-1] + +# [Tests] +# >>> corrige_mois(2, 2016) +# 6 +# >>> corrige_mois(9, 2014) +# 2 + + +# [Q] Programmez une fonction nommée num_jour, paramétrée par trois +# entiers représentant une date supposée valide, qui renvoie le numéro du jour +# dans la semaine correspondant à cette date. +def num_jour(j, m, a): + """ + Renvoie le numéro du jour dans la semaine correspondant à la date donnée. + + CU : Date valide (selon est_date_valide()) + + Exemple : + + >>> num_jour(9, 11, 2004) + 2 + """ + # On peut utiliser le prélicat est_date_valide() précédemment écrite + # ce qui nous permet de nous libérer d'instructions assert() et de CU + assert(est_date_valide(j, m, a)), "La date n'est pas valide" + # On stocke les valeurs utilisées plusieurs fois dans des variables pour + # éviter de refaire deux fois le même calcul + ab = a//100 + cd = a%100 + return (cd//4 + ab//4 + cd + corrige_mois(m, a) + j + 2 + 5 * ab) % 7 + +# [Tests] +# >>> num_jour(9, 11, 2004) +# 2 +# >>> num_jour(24, 10, 1929) +# 4 + + +# [Q] Programmez une fonction nommée nom_jour +def nom_jour(j, m, a): + """ + Renvoie le nom du jour dans la semaine correspondant à la date donnée. + + CU : Date valide (selon est_date_valide()) + + Exemple : + + >>> nom_jour(24, 10, 1929) + "Jeudi" + """ + assert(est_date_valide(j, m, a)), "La date n'est pas valide" + num = num_jour(j, m, a) + # Au cas où la fonction num_jour() viendrait à dysfonctionner + assert(num in range(7)), "Jour de la semaine inconnu" + # On stocke les jours dans un tableau pour un accès facilité + liste_jours_semaine = ["Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", \ + "Vendredi", "Samedi"] + return liste_jours_semaine[num] + +# [Tests] +# >>> nom_jour(24, 10, 1929) +# 'Jeudi' +# >>> nom_jour(9, 11, 2004) +# 'Mardi' + + +# [Q] Programmez une procédure imprimer_mois +def imprimer_mois(m, a): + """ + Imprime le calendrier du mois de l'année donné. + + CU : m entier, a entier, 1 ≤ m ≤ 12, a > 1582 + + Exemple : + >>> imprimer_mois(9, 2014) + Septembre 2014 + di lu ma me je ve sa + 1 2 3 4 5 6 + 7 8 9 10 11 12 13 + 14 15 16 17 18 19 20 + 21 22 23 24 25 26 27 + 28 29 30 + """ + assert(type(a) is int and a > 1582), \ + "L'année doit être un entier supérieur à 1582" + assert(type(m) is int and m in range(1, 13)), \ + "Le mois doit être un entier compris entre 1 et 12 inclus" + + # Affichage mois et année + # On stocke les mois dans un tableau pour un accès facilité + liste_mois = ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", \ + "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"] + # On enlève 1 à l'index du tableau, car les mois comment à 1 + # alors que le tableau commence lui à 0 + # On stocke dans une variable le titre brut (sans alignement / espacement) + titre = liste_mois[m-1] + " " + str(a) + # On affiche le titre centré en répètant sur la droite un certain nombre + # de caractères d'espacements. Ce dernier est calculé en enlevant la + # longueur du titre àl a longueur maximale de la ligne et en divisant le + # tout par deux + print(" " * ((20-len(titre))//2) + titre) + # Affichage nom des jours de la semaine + print("di lu ma me je ve sa") + # Affichage des jours + jour = 1 # Le jour à écrire (s'incrémente) + jour_semaine_1er = num_jour(jour, m, a) # Premier jour de la semaine + nbre_jours_mois = nbre_jours(m, a) # Nombre de jours du mois + # Boucle sur les lignes. + # Ne s'arrête pas tant que le jour final a été atteint + while jour <= nbre_jours_mois: + # La variable ligne stockera la ligne avant de l'imprimer + ligne = "" # On l'initialise / l'efface + # Boucle sur les jours de la semaine. + for jour_semaine in range(7): + # Si on en est au premier jour (donc sur la première ligne) mais que + # le premier jour n'a pas été dépassé, on ajoute du "vide" + if jour == 1 and jour_semaine < jour_semaine_1er: + ligne += " " + # Sinon, et si on a pas dépassé le nombre de jours + elif jour <= nbre_jours_mois: + # On ajoute un caractère d'espacement si le nombre ne possède + # qu'un chiffre pour l'aligner à droite + if jour < 10: + ligne += " " + # On ajoute le nombre du jour + ligne += str(jour) + # On incrémente jour pour passer au prochain jour + jour += 1 + # Si on est entre deux jours, on ajoute un caractère d'espacement + if jour_semaine < 6 and jour <= nbre_jours_mois: + ligne += " " + print(ligne) # On affiche la ligne + +# [Tests] +# >>> imprimer_mois(9, 2014) +# Septembre 2014 +# di lu ma me je ve sa +# 1 2 3 4 5 6 +# 7 8 9 10 11 12 13 +# 14 15 16 17 18 19 20 +# 21 22 23 24 25 26 27 +# 28 29 30 +# >>> imprimer_mois(5, 1968) +# Mai 1968 +# di lu ma me je ve sa +# 1 2 3 4 +# 5 6 7 8 9 10 11 +# 12 13 14 15 16 17 18 +# 19 20 21 22 23 24 25 +# 26 27 28 29 30 31 + + +# [Q] Écrivez une instruction utilisant la procédure imprimer_mois pour +# imprimer tous les mois de cette année +# Boucle sur les mois +for mois in range(1, 13): + imprimer_mois(mois, 2014) + # Si on est entre deux mois, on ajoute une ligne d'espacement + if mois < 12: + print("")