On suppose défini le type arbre de la manière suivante :
type arbre =
|Feuille of int
|Noeud of arbre * arbre ;;
On dit qu'un arbre est un peigne si tous les noeuds à l'exception éventuelle de la racine ont au moins une feuille pour fils. On dit qu'un peigne est un strict si sa racine a au moins une feuille pour fils, ou s'il est réduit à une feuille. On dit qu'un peigne est rangé si le fils droit d'un noeud est toujours une feuille. Un arbre réduit à une feuille est un peigne rangé.
Figure 1 : un peigne à cinq feuilles
Représenter un peigne rangé à 5 feuilles.
La hauteur d'un arbre est le nombre de noeuds maximal que l'on rencontre pour aller de la racine à une feuille (la hauteur d'une feuille seule est 0 ). Quelle est la hauteur d'un peigne rangé à feuilles? On justifiera la réponse.
Ecrire une fonction est_range : arbre bool qui renvoie true si l'arbre donné en argument est un peigne rangé.
Ecrire une fonction est_peigne_strict : arbre bool qui renvoie true si l'arbre donné en argument est un peigne strict. En déduire une fonction est_peigne : arbre bool qui renvoie true si l'arbre donné en argument est un peigne.
On souhaite ranger un peigne donné. Supposons que le fils droit de sa racine ne soit pas une feuille. Notons le sous-arbre gauche de la racine, l'une des feuilles du noeud et l'autre sous-arbre du noeud . On va utiliser l'opération de rotation qui construit un nouveau peigne où
le fils droit de la racine est le sous-arbre ;
le fils gauche de la racine est un noeud de sous-arbre gauche et de sous-rabre droit la feuille .
Figure 2 : une rotation
(a) Donner le résultat d'une rotation sur l'arbre de la figure 1.
(b) Ecrire une fonction rotation : arbre arbre qui effectue l'opération décrite ci-dessus. La fonction renverra l'arbre initial si une rotation n'est pas possible.
(c) Ecrire une fonction rangement : arbre arbre qui range un peigne donné en argument, c'est à dire qu'il renvoie un peigne rangé ayant les mêmes feuilles que celui donné en argument. La fonction renverra l'arbre initial si celui-ci n'est pas un peigne.
Exercice 2
Dans une classe de élèves, les élèves sont numérotés de 0 à . Un professeur souhaite faire l'appel, c'est à dire déterminer quels élèves sont absents.
Partie A
Ecrire une fonction mini : int list (int * int list) qui prend en argument une liste non vide d'entiers distincts, et renvoie le plus petit élément de cette liste, ainsi que la liste de départ privée de cet élément (pas forcément dans l'ordre initial).
En notant la longueur de la liste donnée en argument, quelle est la complexité en nombre de comparaisons de la fonction précédente?
En utilisant la fonction mini, écrire une fonction absents : int list int int list qui, étant donné une liste non vide d'entiers distincts et , renvoie, dans un ordre quelconque, la liste des entiers de qui n'y sont pas.
En notant la longueur de la liste donnée en argument, quelle est la complexité en nombre de comparaisons (en fonction de et ) de la fonction précédente?
Partie B
Dans cette partie, une salle de classe pour élèves est décrite par la donnée d'un tableau à entrées. Si tab est un tel tableau et i un entier de , alors tab. (i) donne le numéro de l'élève assis à la place (ou -1 si cette place est vide).
5. Ecrire une fonction asseoir : int list int int vect, qui prend en argument une liste non vide d'entiers distincts et un entier , et renvoie un tableau représentant une salle de classe pour élèves où chaque élève de la liste à été assis à la place numérotée par son propre numéro. Les entiers supérieurs ou égaux à seront ignorés.
6. En déduire une fonction absent2 : int list int int list qui étant donné une liste non vide d'entiers distincts et un entier , renvoie la liste des entiers de qui n'y sont pas. Les entiers supérieurs ou égaux à seront ignorés.
7. En notant la longueur de la liste donnée en argument, quelle est la complexité en nombre de lectures et d'écritures dans un tableau (en fonction de et ) de la fonction précédente?
Partie C
Dans cette partie indépendante des précédentes, les élèves sont déjà assis en classe.
8. On considère la fonction place : int vect unit suivante :
let rec place tab i =
if i <> -1 then
begin
let temp=tab.(i) in
tab.(i) <- i;
place tab temp
end;;
On note classe le tableau (on suppose dans cette question). Donner le tableau classe après l'exécution de place classe 1. On donnera l'état de la variable classe à chaque appel récursif de la fonction.
9. On considère la fonction placement : int vect int unit ci-dessous :
let placement tab n =
for i=0 to n-1 do
if tab.(i) <> -1 && tab.(i) <>i then
begin
let temp=tab.(i) in
tab.(i) <- -1;
place tab temp
end
done;;
Si classe est un tableau d'entiers (les entiers positifs sont distincts) représentant une classe, que fait placement classe?
Exercice 3
On rappelle la définition de la suite de Fibonacci :
Partie A. Calcul des termes de la suite
On considère la fonction fibo : int int suivante :
let rec fibo = function
|0->0
|1->1
|n->fibo (n-1) + fibo (n-2);;
Pourquoi est-ce une mauvaise idée d'utiliser cette fonction pour calculer ?
2. Ecrire une fonction fibo2 : int int qui, étant donné , calcule en effectuant un nombre linéaire en d'additions.
Partie B. Décomposition de Zeckendorf
Pour , on appelle décomposition de Zeckendorf de une décomposition de comme somme de termes distincts (d'indices supérieurs ou égal à 2 ) de la suite de Fibonacci, de telle manière qu'il n'y ait pas deux termes d'indices consécutifs dans la somme. Autrement dit, il existe des indices tels que :
,
pour tout (pas d'indices consécutifs),
.
Par exemple, est une décomposition de Zeckendorf de 7 (avec et ), alors que n'est pas une décomposition de Zeckendorf de 8 car et sont deux termes consécutifs de la suite de Fibonacci.
3. Déterminer une décomposition de Zeckendorf de 20,21 et 22 .
4. Montrer que tout entier strictement positif admet une décomposition de Zeckendorf (on admet qu'elle est unique).
Partie B. Codage de Fibonacci
On appelle codage de Fibonacci d'un entier positif un tableau tab de 0 et de 1 indiquant par des 1 les indices des termes de la suite de Fibonacci utilisés dans la décomposition de Zeckendorf de (tab.(0) indique alors si est utilisé dans la représentation). On remarque que par définition de la décomposition de Zeckendorf, tab ne peut contenir deux 1 consécutifs. est ainsi un codage de Fibonacci de 7
5. Ecrire une fonction decode : int vect int qui traduit en entier une représentation de Fibonacci d'un entier.
6. (a) Decrire sans l'implémenter une fonction plusun : int vect int vect, qui à partir d'une représentation de Fibonacci d'un entier , renvoie une représentation de Fibonacci de l'entier .
(b) Decrire sans l'implémenter une fonction moinsun : int vect int vect, qui à partir d'une représentation de Fibonacci d'un entier non nul, renvoie une représentation de Fibonacci de l'entier .
Exercice 4
Dans cet exercice, les programmes seront écrits avec le langage Python. On pourra utiliser si besoin la bibliothèque numpy :
renvoie un tableau bidimensionnel ( ) rempli de 0 ;
si T est un tableau bidimensionnel, accède à l'élément ligne et colonne de ce tableau.
Le réseau de métro d'une grande ville comporte stations réparties sur un certain nombre de lignes interconnectées (par exemple, pour la ville de Lyon, on a avec 4 lignes).
On représente ce réseau par un graphe non orienté défini par :
l'ensemble des sommets est ; on a numéroté les stations de 0 à . Le sommet du graphe représente la station ;
désigne l'ensemble des arêtes de . Un arête entre les sommets et (éléments de ) n'existe que si les stations et sont des stations adjacentes sur une même ligne de métro. Ce graphe est représenté par la liste Liste_A (donnée en variable globale) de ses arêtes sous la forme tels que .
Ecrire une fonction voisin_G qui prend en entrée un entier et reourne la liste des sommets adjacents à dans .
On suppose le graphe connexe et on cherche à déterminer le trajet le plus rapide entre deux stations du réseau.
Soit duree la fonction définie sur qui attribue à une arête la durée du trajet entre la station et la station en minutes, arrondie sur un nombre entier.
Un trajet entre deux stations et correspond à un chemin dans qui part de et arrive en . La durée d'un tel trajet utilisant arêtes est la somme des durées des arêtes:
Pour simplifier, on ne tient pas compte des durées correspondant aux changements de métro.
On dispose de la liste Duree des listes , pour tels que . On note la valeur for in Duree
2. Soient deux sommets de . Démontrer qu'il existe au moins un trajet de durée minimale entre et .
Pour sommets de , on note la durée minimale d'un trajet entre et .
3. Soient deux sommets de . Soit un chemin dans qui part de et arrive en en utilisant arêtes ( ). On suppose que ce chemin réalise un trajet de durée minimale entre et . Justifier que pour tout entre 1 et est un trajet de durée minimale entre et et est un trajet de durée minimale entre et .
4. En déduire, pour et distincts tels que , une expression de en fonction des valeurs et pour parcourant la liste des sommets de à l'exception de et . Justifier votre réponse.
5. Définir Tinit le tableau bidimensionnel ( ) tel que
Définir la fonction FW qui prend en antrée un tableau bidimensionnel et retourne le tableau bidimensionnel défini par
Ecrire un programme qui, en utilisant le tableau Tinit et la fonction FW, permet de calculer un tableau bidimensionnel ( ) dont le ( )-ième coefficient vaut , pour tous sommets et . Combien d'itérations sont-elles nécessaires pour conclure?
Expliquer comment modifier le programme pour obtenir un trajet de durée minimale entre et pour tous sommets . On ne demande pas de le programmer précisément mais d'expliquer ce qu'il faudrait ajouter au programme précédent pour obtenir de plus ces informations.
E3A Option Informatique MP 2017 - Version Web LaTeX | WikiPrépa | WikiPrépa