Pour les questions suivantes, vous proposerez, dans la mesure du possible, au moins deux versions de chaque fonction demandée nom_de_la_fonction1()
,nom_de_la_fonction2()
, … en utilisant les différentes façons de construire une liste (explicitement, par concaténation, par compréhension).
a) Écrire une fonction
carres()
de paramètren
, un nombre entier positif, et qui retourne la liste des \(n\) premiers carrés.
Jeu de test:
>>> carres(7)
[0, 1, 4, 9, 16, 25, 36]
b) Écrire une fonction
carres_inf()
de paramètren
, un nombre entier positif, et qui retourne la liste des carrés inférieurs à \(n\).
Jeu de test:
>>> carres_inf(50)
[0, 1, 4, 9, 16, 25, 36, 49]
c) Écrire une fonction
carres_digits()
de paramètredigits
, un nombre entier positif, et qui retourne la liste des carrés qui s’écrivent avec exactement un nombre de chiffres égal àdigits
.
Jeu de test:
>>> carres_digits(2)
[16, 25, 36, 49, 64, 81]
d) Écrire une fonction
carres_digits_finissant()
de paramètresdigits
etdernier
, deux nombres entiers positifs, et qui retourne la liste des carrés qui s’écrivent avec exactement un nombre de chiffres égal àdigits
et qui commencent par le chiffredernier
.
Jeu de test:
>>> carres_digits_finissant(3, 9)
[169, 289, 529, 729]
e) Écrire une fonction
carres_palindromes()
de paramètredigits
, un nombre entier positif, et qui retourne la liste des carrés qui s’écrivent avec exactement un nombre de chiffres égal àdigits
et dont l’écriture décimale est un palindrome (exemple: “kayak” est un palindrome puisque ce mot écrit à l’envers est lui-même).
Jeu de test:
>>> carres_palindromes(3)
[121, 484, 676]
Nous allons ici simuler le déplacement de véhicules dans une file sur un circuit où quelques règles sont imposées:
a) Interdiction de sortir de la file (pas de dépassement, …) ou du
circuit,
b) Sens de parcours: de droite vers la gauche,
c) Un véhicule peut avancer uniquement si la case devant lui est libre. En
particulier, le véhicule le plus a gauche peut avancer si la case la plus à
droite est libre.
La file sera une liste de 0
(case vide) et de 1
(véhicule présent).
On considère dans cette partie que les véhicules avancent en même temps pour ceux qui le peuvent.
Autrement dit, à chaque étape, on détermine la nouvelle file une fois tous les déplacements simultanés effectués à partir de la file précédente.
a) Sur papier, déterminer la file suivante si l’on part de
file = [1, 0, 1, 1, 1, 0, 0, 1, 0, 0]
.
b) Écrire une fonction
initialisation_file()
de paramètrelongueur
qui retourne une file aléatoire de longueur souhaitée.
Jeu de test:
>>> file = initialisation_file(5)
>>> len(file) == 5
True
c) Écrire un prédicat
est_libre()
de paramètresfile
,index
qui renvoieTrue
si la case représentée parfile[index]
est libre (sans véhicule). Vous prêterez attention aux valeurs possibles prises parindex
.
Jeu de tests:
>>> file = [1, 0, 1, 1, 0]
>>> est_libre(file, -1)
True
>>> est_libre(file, 2)
False
d) Écrire une fonction
evolution_synchro()
de paramètrefile
qui retourne lafile
à l’étape suivante.
Jeu de test:
>>> file = [1, 0, 1, 1, 1, 0, 0, 1, 0, 0]
>>> evolution_synchro(file)
[0, 1, 0, 1, 1, 0, 1, 0, 0, 1]
e) Écrire une fonction
afficher()
de paramètresfile
etetape
(on pourra considérer ce dernier en paramètre optionnel de valeur par défaut0
) qui affichera dans la console un message donnant le numéro de l’étape ainsi que l’état de la file. On supposera que la file à l’étape n°0 désigne la file de départ.
Jeu de test:
>>> file = [0, 1, 0, 1, 1, 0, 1, 0, 0, 1]
>>> afficher(file, 1)
Etape n°1 [0, 1, 0, 1, 1, 0, 1, 0, 0, 1]
f) Appliquer les fonctions précédentes afin de déterminer l’état de la file lors des dix premières étapes, puis jusqu’à l’étape n°100.
Bonus ! Si vous souhaitez avoir un résultat plus joli. Vous pourrez ajouter ce qui suit dans votre script.
Vous aurez noter que le résultat est surprenant, mais que ce n’est pas très réaliste de ce que l’on peut observer sur un circuit avec les mêmes règles.
Une première possibilité d’amélioration est d’ajouter un paramètre
proba_avancer
pour tenir compte du fait qu’un véhicule a une certaine
probabilité d’avancer dans le cas où il le peut.
g) Proposer une modification de la fonction
evolution_synchro()
de sorte qu’elle accepte deux paramètresfile
etproba_avancer
pour tenir compte de l’amélioration souhaitée
Jeu de test:
>>> file = [1, 0, 1, 1, 0]
>>> possibilites = [[1, 0, 1, 1, 0],\
[0, 0, 1, 1, 1],\
[1, 1, 0, 1, 0],\
[0, 1, 0, 1, 1]]
>>> evolution_synchro(file, 50) in possibilites
True
Faire bouger tous les véhicules en même temps ? Pas très réaliste ! Une solution: désynchroniser les mouvements des véhicules !
Les véhicules bougent les uns après les autres pour ceux qui le peuvent.
Autrement dit, à chaque étape, on modifie directement la file après l’éventuel déplacement d’un des véhicules. En détail, on choisit un élément au hasard de cette file, puis on applique la règle de déplacement.
h) Proposer une fonction
evolution_asynchro()
qui prend comme paramètrefile
et qui retourne la file ainsi modifiée de la façon présentée ci-dessus. Une fois réalisée, vous pourrez ajouter le paramètre supplémentaireproba_avancer
(défini dans la partie précédente).
Jeu de test:
>>> file = [1, 0, 1, 1, 0]
>>> possibilites = [[1, 0, 1, 1, 0],\
[0, 0, 1, 1, 1],\
[1, 1, 0, 1, 0],\
[0, 1, 0, 1, 1]]
>>> evolution_a1(file) in possibilites
True
i) Admirez le résultat avec la fonction
afficher()
ou mieux avecafficher2()
.
Là encore, c’est perfectible. Vous aurez noté que certains éléments de file
peuvent être choisies plus souvent que d’autres. On peut améliorer la fonction
précédente en listant les véhicules susceptibles de bouger, puis de choisir un
par un au hasard les véhicules de cette liste, et enfin, seulement une fois que
l’on aura épuisé cette liste, répéter le procédé: “lister, choisir jusqu’à
épuisement de la liste, …”.
Nous allons simuler cette fois l’évolution d’un feu de forêt.
La forêt sera représentée par une grille aussi appelée tableau où chaque
case peut être dans l’un des 4 états: 0
(clairière), 1
(cendres), 2
(feux) et 3
(arbres).
Partons du principe que le feu suit les règles suivantes:
a) une clairière ne brûle pas,
b) les cendres restent cendres,
c) des arbres en feu deviennent cendres,
b) des arbres prennent feu si ils ont un de leurs 4 voisins (Nord, Sud, Est,
Ouest) en feu (voir figure ci-dessous).
a) Écrire une fonction nommée
grille()
prenant deux paramètrescolonnes
etlignes
qui désignent respectivement le nombre de colonnes et le nombre de lignes de la grille désirée.
Jeu de test:
>>> grille(3,2)
[[0, 0, 0], [0, 0, 0]]
b) Écrire deux fonctions nommées
nb_colonnes()
pour la première etnb_lignes()
pour l’autre qui prennent toutes deux comme paramètregrille
, un tableau, et qui renvoient respectivement le nombre de colonnes et le nombre de lignes de la grille donnée.
Jeux de test:
>>> grille = [[3, 0, 3],[1, 2, 3]]
>>> nb_colonnes(grille)
3
et
>>> grille = [[3, 0, 3],[1, 2, 3]]
>>> nb_lignes(grille)
2
c) Écrire une fonction
effectif()
de paramètresgrille
etetat
qui renvoie le nombre de cases de cette grille dans cet état.
Jeu de test:
>>> grille = [[3, 0, 3],[1, 2, 3]]
>>> effectif(grille, 3)
3
d) Écrire une fonction
surface()
de paramètregrille
qui renvoie le nombre de cases qui composent cette grille.
Jeu de test:
>>> grille = [[3, 0, 3],[1, 2, 3]]
>>> surface(grille)
6
e) Écrire une fonction
proportion()
de paramètresgrille
etetat
qui renvoie la proportion de cases de cette grille dans cet état.
Jeu de test:
>>> grille = [[3, 0, 3],[1, 2, 3]]
>>> proportion(grille, 3)
50.0
f) Écrire une fonction
voisins()
de paramètresgrille
,etat
,c
etl
qui renvoie la liste des coordonnées des cases voisines à la case de coordonnées (c, l) dans cet état.
Jeu de test:
>>> grille = [[3, 3, 3],\
[3, 0, 3],\
[0, 3, 3],\
[3, 2, 3]]
>>> len(voisins(grille, 2, 2, 3))
1
>>> voisins(grille, 2, 2, 3)
[(1, 3)]
>>> len(voisins(grille, 3, 1, 0))
2
>>> (0,0) in voisins(grille, 3, 1, 0) and \
(2,0) in voisins(grille, 3, 1, 0)
True
>>> len(voisins(grille, 3, 1, 1))
4
>>> (1,0) in voisins(grille, 3, 1, 1) and \
(1,2) in voisins(grille, 3, 1, 1) and \
(0,1) in voisins(grille, 3, 1, 1) and \
(2,1) in voisins(grille, 3, 1, 1)
True
g) Proposer une fonction
afficher()
de paramètregrille
qui affiche dans la console la grille.
Jeu de test:
>>> grille = [[3, 0, 3],\
[1, 2, 3]]
>>> afficher(grille)
+---+---+---+
| 3 | 0 | 3 |
+---+---+---+
| 1 | 2 | 3 |
+---+---+---+
h) Écrire une fonction
initialisation()
de paramètrescolonnes
,lignes
etp
. Cette fonction renvoie la forêt sous forme d’un tableau avec uniquement des clairières et des arbres dans la proportion souhaitée désignée par la variablep
.
Jeu de test:
>>> foret = initialisation_foret(3, 2)
>>> all(foret[l][c] in {0, 1, 2, 3} for l in range(2) for c in range(3))
True
i) Écrire une fonction
depart_feu()
de paramètreforet
qui renvoie cette forêt dans laquelle un départ de feu s’est déclaré de manière aléatoire dans l’une des cases contenant des arbres.
Jeu de test:
>>> foret = [[0, 0, 3],\
[0, 0, 0]]
>>> depart_feu(foret)
[[0, 0, 2], [0, 0, 0]]
j) Écrire une fonction
evolution()
de paramètreforet
et qui renvoie une nouvelle grille représentant cette forêt après propagation des flammes suivant la règle donnée en début d’énoncé (méthode synchrone).
Jeu de test:
>>> foret = [[3, 3, 3],\
[3, 0, 3],\
[0, 3, 3],\
[3, 2, 3]]
>>> foret = evolution(foret)
>>> foret
[[3, 3, 3], [3, 0, 3], [0, 2, 3], [2, 1, 2]]
k) Pour finir, réaliser une procédure
generer()
qui prend en paramètreforet
et qui va afficher l’évolution de cette forêt au fur et à mesure du temps jusqu’à ce que le feu s’éteigne. Afin de mieux visualiser l’évolution nous ferons une pause d’une seconde entre chaque génération. La fonctionsleep
du moduletime
vous permettra de faire une telle pause (allez voir la documentation de cette fonction pour savoir comment l’utiliser).
Bonus ! Si vous souhaitez avoir un résultat plus joli et garder en mémoire l’évolution des flammes dans cet forêt. Vous pourrez ajouter ce qui suit dans votre script.