Consignes

Si certains exercices n'ont pas pu être terminés dans le cadre de cette séance, il est fortement conseillé de les terminer par vous-même chez vous ou en salle libre service.

Liens utiles

Objectifs du TP

Le but de ce TP est de poursuivre l'apprentissage de la manipulation des tableaux. Il vous permet également d'être confronté à une démarche d'analyse descendante d'un problème donné (cf. cours).

1. Ecriture des fonctions de base pour manipuler une date

On représente une date à l'aide d'un tableau de trois entiers correspondant, dans l'ordre d'apparition dans le tableau, au jour, au mois et à l'année. Ainsi, par exemple :

Pour rendre plus lisibles les programmes que nous allons écrire dans ce TP, nous allons introduire :

Exemple :

>>> cree_date(20, 10, 2014)
[20, 10, 2014]
>>> get_jour([20, 10, 2014])
20
>>> get_mois([20, 10, 2014])
10
>>> get_an([20, 10, 2014])
2014

Ecrire les fonctions cree_date, get_jour, get_mois et get_an. Vous les utiliserez dans la suite du TP.

2. Retour vers le futur...

Écrire une fonction decale_date qui prend en paramètres :

et renvoie la date correspondant à une avancée de n jours dans le temps à partir de la date donnée. Par exemple :

Exemple :

>>> decale_date([20, 10, 2014], 7)
[27, 10, 2014]
>>> decale_date([31, 12, 2014], 1)
[1, 1, 2015]

Pour écrire cette fonction, vous supposerez qu'il existe une fonction lendemain prenant une date en paramètre et renvoyant la date du lendemain. Utilisez-la pour définir decale_date : cela simplifiera grandement votre travail.

Faites valider ce que vous avez écrit à votre enseignant de TP. Il ne vous sera en effet pas possible, pour le moment, de tester votre fonction puisque la fonction lendemain n'existe pas encore. C'est l'objectif de la question suivante que de définir lendemain. Lorsqu'elle sera définie, vous pourrez alors tester decale_date. Nous laissons de fait de côté, pour le moment, le test de decale_date et nous passons à la définition de lendemain.

Calcul de la date du lendemain

Écrire une fonction lendemain qui prend une date en paramètre et renvoie la date du lendemain.

Exemple :

>>> lendemain([20, 10, 2014])
[21, 10, 2014]
>>> lendemain([31, 12, 2014])
[1, 1, 2015]
>>> lendemain([31, 10, 2014])
[1, 11, 2014]
>>> lendemain([29, 2, 2012])
[1, 3, 2012]

Nous allons ici aussi introduire des fonctions qui vont nous "faciliter la vie" pour définir lendemain. Dans le cadre d'une démarche d'analyse descendante, il faudrait supposer l'existence de ces fonctions, les utiliser pour écrire lendemain, les définir ensuite. L'inconvénient est qu'il n'est pas possible de tester tant que toutes les fonctions ne sont pas définies. Nous allons donc procéder "à l'envers". Laissons de côté pour le moment l'écriture de la fonction lendemain. Nous y reviendrons lorsque les fonctions ci-dessous auront été définies.

Fin d'année

Écrire une fonction fin_d_annee qui prend une date en paramètre et teste si cette date correspond à la fin de l'année (c'est-à-dire au 31 décembre).

Fin de mois

Ecrire une fonction fin_de_mois qui prend une date en paramètre et teste si cette date correspond à une fin de mois.

Exemple :

>>>fin_de_mois([20, 10, 2014])
False
>>> fin_de_mois([31, 12, 2014])
True
>>> fin_de_mois([31, 10, 2014])
True
>>> fin_de_mois([28, 2, 2012])
False
>>> fin_de_mois([29, 2, 2012])
True

Pour écrire cette fonction, il faut au préalable définir les fonctions est_bissextile et nb_jours_ds_mois.

La fonction est_bissextile prend en paramètre un entier correspondant à une année et teste si cette année est bissextile. Cette fonction est utilisée dans la définition de nb_jours_ds_mois (cf. ci-dessous). Il est de fait nécessaire de la définir au préalable. Pour rappel, une année A est bissextile si A est multiple de 4, mais pas de 100, ou multiple de 400.

Exemple :

>>> est_bissextile(2014)
False
>>> est_bissextile(2012)
True
>>> est_bissextile(2000)
True
>>> est_bissextile(1900)
False

La fonction nb_jours_ds_mois prend en paramètres :

- un entier mois correspondant à un numéro de mois - un entier annee correspondant à un numéro d'année -

et renvoie le nombre de jours dans un mois donné, étant donné une année donnée. Le paramètre année est nécessaire du fait des années bissextiles : février n'a en effet pas le même nombre de jours selon que l'année est bissextile ou pas.

Exemple :

>>> nb_jours_ds_mois(5, 2014)
31
>>> nb_jours_ds_mois(2, 2012)
29
>>> nb_jours_ds_mois(2, 2014)
28

La fonction nb_jours_ds_mois est celle que vous avez écrite dans le CC1. Il s'agissait du dernier exercice.

Calcul de la date du lendemain : le retour !

Nous avions laissé de côté l'écriture de la fonction lendemain car il fallait au préalable en définir d'autres (fin_de_mois, fin_d_annee, etc.). Ces fonctions sont maintenant définies : il est possible de les utiliser ppur écrire lendemain.

Décalage de n jours dans le temps : le retour (pour tests)

Nous avions laissé de côté le test de la fonction decale_date car il fallait au préalable définir lendemain. C'est maintenant chose faite; il est de fait possible de tester decale_date.

Tester la fonction decale_date en prenant des exemples de dates pertinents.

3. Calendrier perpétuel

- Maman, c'était quel jour quand je suis né ?
- Ououououh... je ne me rappelle plus bien. Il me semble que c''était un lundi... mais peut-être un samedi aussi. J''hésite... Demande donc à ton père.
- ...
- Papa, tu sais quel jour c'était quand je suis né ?
- C'était un mercredi ! Je suis sûr, parce que ce jour-là, ta mère ... blablabla, blablabla...

Vous voilà bien avancé : ni Maman, ni Papa ne se souviennent exactement. Et cette question fondamentale va vous hanter pendant tout le reste de votre existence. Et si vous épatiez Papa et Maman en leur apportant vous-même la réponse ? Et si, non content de cela, vous leur donniez, en plus, le jour de leur propre naissance ? Quelle gloire ce serait pour vous ! C'est ce que nous vous proposons de faire dans cette partie en travaillant sur la notion de calendrier perpétuel.

Un calendrier perpétuel (voir Wikipedia) est un calendrier qui donne le jour de la semaine (lundi, mardi, mercredi, ...) correspondant à une date donnée. Nous allons, dans cette partie, écrire une fonction calendrier_perpetuel prenant une date en paramètre et renvoyant une chaîne de caractères correspondant au jour de la semaine de cette date. Nous ne traiterons que les dates appartenant au calendrier grégorien, c'est-à-dire à partir du 20 décembre 1582 en France.

Exemple :

>>> calendrier_perpetuel([20, 10, 2014])
"lundi"
>>> calendrier_perpetuel([8, 10, 2003])
"mercredi"
>>> calendrier_perpetuel([1, 6, 2014])
"dimanche"
>>> calendrier_perpetuel([7, 1, 1994])
"vendredi"

C'est M. Moret qui a proposé ce calendrier. Il est composé, dans sa version initiale, de 3 tableaux dans lesquels il faut aller chercher des chiffres en fonction de la date en entrée et faire ensuite des calculs sur ces chiffres. Une version simplifiée a été proposée. Elle consiste à attribuer :

et à faire leur somme. Tous ces nombres sont définis modulo 7 (ex : 5 est équivalent à 12, 19, 26, ...). Le résultat de l'addition, modulo 7 lui aussi, est un nombre compris entre 0 et 6, qui donne le jour de la semaine selon la correspondance suivante :

Nous allons définir, dans ce qui suit, des fonctions permettant de calculer les nombres séculaire, annuel, mensuel et le quantième d'une date donnée. Nous les utiliserons pour définir la fonction calendrier_perpetuel.

Nombre séculaire

Le « nombre séculaire » est le même pour toutes les années commençant par les deux mêmes chiffres. Par exemple, toutes les années du 21ème siècle (années 2001 à 2099) auront un nombre séculaire égal à 0. C'est également le cas de l'année 2000.

Le tableau suivant donne les nombres séculaires pour chaque siècle :

Il est à noter que ce nombre diminue de deux unités chaque siècle (modulo 7) sauf lorsque les deux premiers chiffres sont un multiple de 4 (1600 à 1699, 2000 à 2099).

Ecrire une fonction nombre_seculaire qui prend une année en paramètre et renvoie le nombre séculaire associé à cette année.

Exemple :

>>> nombre_seculaire(2014)
0
>>> nombre_seculaire(1996)
1

Vous pourrez introduire des fonctions intermédiaires pour écrire cette fonction, par exemple la fonction siecle qui prend en paramètre une année A et renvoie le nombre correspondant au siècle de A.

Exemple :

>>> siecle(2014)
20
>>> siecle(1996)
19
>>> siecle(1900)
19

Nombre annuel

La ligne ci-dessous mentionne les années pour lesquelles le nombre annuel est égal à 0. À partir de ces années, le nombre annuel augmente d'une unité chaque année et de deux si l'année est bissextile.

Années dont le nombre annuel est 0 :

..04 ..10 ..21 ..27 ..32 ..38 ..49 ..55 ..60 ..66 ..77 ..83 ..88 ..94

Exemple :

On peut aussi remarquer que le résultat est donné par la formule suivante :

Exemple pour l'année 2010 :

Exemple pour l'année 2016 :

Ecrire une fonction nombre_annuel qui prend une année en paramètre et renvoie le nombre annuel associé à cette année.

Exemple :

>>> nombre_annuel(2010)
0
>>> nombre_annuel(2016)
1

Vous pourrez introduire des fonctions intermédiaires pour écrire cette fonction, par exemple la fonction an qui prend en paramètre une année A et renvoie le nombre correspondant aux 2 derniers chiffres de A.

Exemple :

>>> an(2014)
14
>>> an(1996)
96
>>> an(1900)
0

Nombre mensuel

Le tableau suivant donne le nombre mensuel pour chaque mois de l'année (cf. Nombre mensuel sur Wikipedia):

Exemple : le mois de janvier a un nombre mensuel de 4 en 1995 et de 3 en 1996 (année bissextile).

Ecrire une fonction nombre_mensuel qui prend en paramètres :

et qui renvoie le nombre mensuel associé à ces données.

Exemple :

>>> nombre_mensuel(1, 1995)
4
>>> nombre_mensuel(1, 1996)
3

Quantième

Le quantième correspond au jour d'une date donnée. Ainsi par exemple :

Ecrire une fonction quantième qui prend une date en paramètre et renvoie le quantième de la date donnée.

Ecriture de la fonction "calendrier_perpetuel"

Ecrire la fonction calendrier_perpetuel qui prend une date en paramètre et renvoie une chaîne de caractères correspondant au jour de la semaine de la date donnée. Vous utiliserez pour cela les fonctions nombre_seculaire, nombre_annuel, nombre_mensuel et quantieme que vous venez d'écrire.

Il vous faut revenir au début de cette partie pour relire les explications sur le calendrier perpétuel et la manière de calculer le jour de la semaine en utilisant les 4 fonctions définies ci-dessus, ainsi que le tableau de correspondance entre un numéro et un jour de la semaine.

Vendredi 13...

Les vendredis 13 ont toujours hanté l'imaginaire collectif. Pour certains, c'est une date maudite et il convient de rester confiné à la maison ce jour-là si l'on ne veut pas prendre le ciel sur la tête. Pour d'autres, c'est une date porte-bonheur.

Ecrire la fonction vendredi_13 qui prend en paramètres :

et calcule le nombre de vendredis 13 qu'il y a entre le 1er janvier de l'année initiale et le 1er janvier de l'année finale. Vous introduirez au préalable une fonction nb_jours permettant de compter le nombre de jours entre ces 2 dates (vous en aurez besoin pour écrire vendredi_13 Pour rappel, une année comporte 365 jours si elle n'est pas bissextile, 366 sinon.

Exemple :

>>> vendredi_13(2014, 2015)
1
>>> vendredi_13(2010, 2014)
7
>>> vendredi_13(2009, 2010)
3

Utilisez cette fonction pour compter le nombre de vendredis 13 entre 1600 et 2000. Que remarquez-vous ?