TP8 : dernier TP avant les écrits¶
Révisions de tout le programme, séance de questions, révisions de la syntaxe et des concepts clés. Basé sur le sujet Mines-Ponts MP/PC/PSI 2015.
Le sujet étudiait un système de tests automatisés pour une usine d’imprimantes.
Documentation¶
TP8 au Lycée Lakanal (sujet rédigé par Arnaud Basson), révisions de tout le programme, séance de questions, révisions de la syntaxe et des concepts clés.
- Dates 1/2 : jeudi 17 et 24 mars (2016).
- Dates 2/2 : dernier TP, jeudi 31 mars (2016).
- Auteur : Arnaud Basson & Lilian Besson, pour le cours d’informatique pour tous en prépa MP (http://perso.crans.org/besson/infoMP/),
- Licence : MIT Licence (http://lbesson.mit-license.org).
-
TP8.
q1
()[source]¶ Réponse à la question I.1.1).
On a \(2^{10} = 1024\), on code les entiers de l’intervalle \([-512, 511]\) par leur reste modulo \(1024\) (il est compris entre \(0\) et \(1023\), donc son écriture binaire comporte au plus \(10\) bits). Cette méthode de codage est appelé le complément à 2 (et ce n’est bien sur pas la seule possible).
Note
On avait déjà vu cette question dans le dernier DS.
-
TP8.
q2
()[source]¶ Réponse à la question I.1.2).
\(10\) bits permettent de représenter \(1024\) valeurs, donc l’intervalle \([-5V, 5V]\) est discrétisé avec \(1024\) points, soit une précision de \(10/1024\), environ égale à \(0.01 V\).
Note
Remarque : soit \(\delta = 10/1024\), les valeurs discrètes des mesures sont les \(k \times \delta\), avec \(k\) entier dans \([-512, 511]\).
-
TP8.
generateur_car
()[source]¶ Fonction simulant la fonction de liaison avec le capteur, non demandée par l’énoncé et non fournie.
Note
Les concepts utilisés par cette fonction ne sont pas au programme de prépa, ne vous embêtez pas à la lire ou la comprendre.
-
TP8.
car_read
(nb)[source]¶ Fausse fonction
car_read
que l’énoncé utilise.Elle fonctionne, mais ne génère pas de séquences de caractères ayant vraiment du sens. Elle permet simplement au code suivant d’être valide, et éventuellement exécuté.
- Exemple :
>>> random.seed(0) # Always the same examples >>> car_read = new_sequence() >>> sequence = car_read(36) >>> print(sequence) P007-159-482+023-190+567-393-0479319
-
TP8.
new_sequence
()[source]¶ Réinitialise le générateur de caractères
car_read()
.A utiliser comme ça :
>>> random.seed(0) # Always the same examples >>> car_read = new_sequence() >>> sequence = car_read(36) >>> print(sequence) P007-159-482+023-190+567-393-0479319 >>> car_read = new_sequence() >>> sequence = car_read(32) >>> print(sequence) I003+511+237-4990249P009+620+804
-
TP8.
q3
()[source]¶ Réponse à la question I.2.3).
car_read(4)
renvoie'+004'
(c’est-à-dire la chaîne formée des \(4\) caractères qui suivent les caractères déjà lus'U003+012'
).
-
TP8.
lecture_trame
(x)[source]¶ Réponse à la question I.2.4).
Le sujet donnait la spécification de cette fonction :
- On lit 3 caractères pour connaître le nombre \(n\) de blocs de données,
- Pour chaque bloc, on lit 4 caractères pour un bloc, qu’on stocke dans
L[k]
(k = 0 .. n-1
), - A la fin, on lit les 4 derniers caractères pour trouver la somme de contrôle
S
.
Avertissement
Ne pas oublier dans cette fonction de faire la conversion des chaînes de caractères renvoyées par
car_read()
en nombres entiers.- Exemple :
>>> random.seed(0) # Always the same examples >>> car_read = new_sequence() >>> sequence = car_read(36) >>> print(sequence) P007-159-482+023-190+567-393-0479319 >>> x, L, S = lecture_trame(sequence) >>> print(L) [-159, -482, 23, -190, 567, -393, -47] >>> print(S) 9319
-
TP8.
checkSum
(trame, reste=10000)[source]¶ Réponse à la question I.2.5).
Il s’agissait simplement d’implémenter la vérification du reste de
sum(L)
modulo \(10000\)(sum(L) % 10000) == S
Note
Pour des sujets comme ça, si rien n’est indique, vous avez normalement le droit d’utiliser les fonctions Python standards
min()
,max()
,sum()
(pour la somme). Attention, pas de fonctionprod()
pour le produit...- Exemple :
>>> random.seed(0) # Always the same examples >>> car_read = new_sequence() >>> sequence = car_read(36) >>> print(sequence) P007-159-482+023-190+567-393-0479319 >>> trame = lecture_trame(sequence) >>> print(trame) ['P007-159-482+023-190+567-393-0479319', [-159, -482, 23, -190, 567, -393, -47], 9319] >>> print(checkSum(trame)) True
-
TP8.
lecture_intensite
()[source]¶ Réponse à la question I.2.7).
La boucle
while True
tourne indéfiniment tant qu’elle n’est pas interrompue de force (par unbreak
ou unreturn
, ou une exception). Ceci nous permet d’attendre l’obtention d’une trame commençant par'I'
, et contenant une somme de contrôle correcte (vérifiée aveccheckSum()
).
-
TP8.
q7
()[source]¶ Réponse à la question II.1.7).
L’intégrale de \(f\) sur \([a, b]\) est approchée selon la méthode des trapèzes (avec \(n+1\) points) par la somme suivante :
\[S = \frac{h}{2} \times \sum_{k=0}^{n-1} \left( f(a + k \times h) + f(a + (k+1) \times h) \right)\]où \(h = \frac{(b-a)}{n}\) est le pas, ce qui donne après simplification :
\[S = \frac{h}{2} \times \left( f(a)/2 + f(a+h) + f(a+2h) + \dots + f(a+(n-1)h) + f(b)/2 \right).\]
-
TP8.
trapezes
(L)[source]¶ Réponse à la question II.1.8).
Si \(L = [a_0, a_1, \dots, a_n]\) alors l’intégrale de \(f\) sur \([0,T]\) est approchée par \(\frac{T}{n} \times (a_0/2 + a_1 + a_2 + \dots + a_{n-1} + a_n/2)\) d’après
q7()
(\(a_k\) étant la valeur de \(f(k T / n)\) et \(T/n\) le pas de temps).La valeur moyenne (sur \([0, 1]\)) est donc approchée par :
\[\begin{split}\frac{1}{n} \times (a_0/2 + a_1 + a_2 + \dots + a_{n-1} + a_n/2) \\ = \frac{1}{n} \times (\mathrm{sum}(a) - a_0/2 - a_n/2) \\\end{split}\]Note
Cette expression ne fait pas intervenir directement T, ni le pas de temps (puisque les valeurs de
L
sont déjà discrétisées temporellement.Attention
Avec ces notations \(a_0, \dots, a_n\), la liste
L
contientn+1
valeurs, attention. Doncn = len(L) - 1
!
-
TP8.
indicateurs
(mesures)[source]¶ Réponse à la question II.1.9).
On calcule la moyenne des mesures, avec la formule des trapèzes, par la fonction
trapezes()
.On pouvait utiliser une boucle
for
ou bien une liste en compréhension pour calculer les écarts quadratique.ecarts_quad = [(f-moy)**2 for f in mesures]
On calcule l’écart-type comme la racine carrée de la moyenne de cette liste
ecarts_quad
.
-
TP8.
omega
= 1¶ omega
sera considéré comme une variable globale. On prend une valeur quelconque (1
).
-
TP8.
simulation
(s0, k, dt=0.002, n=500)[source]¶ Réponse à la question II.2.10).
Ici il fallait utiliser un schéma d’Euler, dans le cas le plus simple : linéaire d’ordre 1, pour résoudre l’équation différentielle suivante :
(1)¶\[\frac{\mathrm{d} s(t)}{\mathrm{d} t} = - \frac{k}{10} (s(t) - e(t))\]Note
Le sujet suggérait d’utiliser
numpy
, donc on utilisenp.sin()
pour calculer le signal d’entréee(t)
.Rappel : si on note
dt
le pas de temps ett[0],...,t[n]
les dates discrétisées (t[i] = i*dt
), la méthode d’Euler a pour but de fournir des approximationss[i]
des valeurs de la solution exacte aux instantst[i]
. Ces approximations sont calculées par la relation de récurrences[i+1] = s[i] - dt \times f(s[i], e[i]) = s[i] - dt \times k/10 \times (s[i] - e(t[i])).
Les paramètres à passer à la fonction simulation sont :
- la valeur initiale
s0 = s(0)
, - et le coefficient
k
(constante dans l’équation (1)), - (
omega
sera considéré comme une variable globale).
Avertissement
Bien sur, on ne pouvait pas utiliser une fonction du module
scipy
(e.g.scipy.integrate.odeint()
) pour calculer directement la solution de l’ED, il fallait implémenter soi-même le schéma d’Euler (les sujets le rappellent généralement).- la valeur initiale
-
TP8.
validation
(mesures, eps)[source]¶ Réponse à la question II.2.11).
Pour chaque
k
dans[0.5, 1.1, 2.0]
, on résout numériquement (avecsimulation()
), puis on teste l’écart maximal entre les valeurs mesurées (mesures[i]
) et les valeurs simuléess[i]
.Note
On voit qu’il fallait bien sur mettre
k
comme un argument de la fonction précédentesimulation()
.Note
Ici aussi, on peut utiliser directement la fonction de base de Python
max()
pour calculer cet écart minimum.La question disait de renvoyer
True
si pour un desk
l’écart maximal est \(\leq eps\), ouFalse
sinon.Note
En français, quand on ne précise pas “inférieur ou égal” ou “inférieur strict”, “inférieur” signifie
<=
(“inférieur ou égal”).Avertissement
Soyez prudents, en français on utilise une virgule
,
pour commencer les décimales, mais en anglais (et donc en Python), c’est un point.
et on utilise une virgule pour séparer les valeurs dans une liste ou un tuple. Il faut donc écrire[0.5, 1.1]
et surtout pas[0,5, 1,1]
ni[0,5; 1,1]
.Le point-virgule
;
n’est pas utilisé en Python. Il peut servir à écrire deux instructions sur la même ligne, mais il ne faut pas s’en servir...Si vous faites aussi du caml, faites attention puisque le
;
est utilise en caml pour séparer les valeurs dans une liste...
-
TP8.
q12
()[source]¶ Réponse SQL à la question III.12).
SELECT nSerie FROM testfin WHERE 0.4 <= Imoy AND Imoy <= 0.5
On peut utiliser
0.4 <= Imoy AND Imoy <= 0.5
ouImoy BETWEEN 0.4 AND 0.5
.
-
TP8.
q13
()[source]¶ Réponse SQL à la question III.13).
SELECT testfin.nSerie, Imoy, Iec, modele FROM testfin JOIN production ON testfin.nSerie = production.nSerie WHERE 0.4 < Imoy AND Imoy < 0.5
Ici il fallait faire la jointure (
table1 JOIN table2 ON table1.attr = table2.attr2
) des deux tablestestfin
etproduction
(selon l’attributnSerie
).Note
Quand
attr1 = attr2
, on peut utiliser le mot cléNATURAL JOIN
mais il vaut mieux éviter (ce n’est pas clair de savoir si c’est au programme ou non).
-
TP8.
q14
()[source]¶ Réponse SQL à la question III.14).
SELECT modele, count(*) as nombreValide FROM production GROUP BY modele
On groupe par modèle les données de la table
production
(GROUP BY modele
). La fonction d’agrégationCOUNT
permet d’obtenir l’effectif de chaque groupe.Note
Le nommage de la deuxième colonne (
as nombreValide
) n’était pas requis.
-
TP8.
q15
()[source]¶ Réponse SQL à la question III.15).
Première solution : avec une sous requête
SELECT nSerie, fichierMes FROM testfin WHERE nSerie NOT IN (SELECT nSerie FROM production)
2. Deuxième solution : avec une différence ensembliste (
EXCEPT
) {imprimantes non validées} = {toutes les imprimantes} {imprimantes validées}. Subtilité : les deux tables dont on fait la différence doivent avoir exactement les mêmes attributs, ce qui oblige à faire une jointure pour ajouter les fichiers de mesures à la deuxième table (celle des imprimantes validées). Cela donne une requête plus complexeSELECT nSerie, fichierMes FROM testfin EXCEPT SELECT testfin.nSerie, fichierMes FROM testfin JOIN production ON testfin.nSerie = production.nSerie
Intérêt: analyser les mesures des imprimantes non validées afin de déterminer le problème ayant empêché leur validation (en vue d’y remédier).
-
TP8.
q16
()[source]¶ Réponse à la question IV.1.16).
Le codage de
'EST'
est1001
, et celui de'ASE'
est1001
aussi.Inconvénient: ce codage n’est pas injectif, donc il ne peut pas être décodé ! (Et donc, il ne sert à rien.)
-
TP8.
q17
()[source]¶ Réponse à la question IV.1.17).
La séquence
101101100000100101111
=10 11 011 000 001 001 011 11
code le mot'RETUOOTE'
.- Ce mot de \(8\) caractères occupe donc \(8\) octets = \(64\) bits en mémoire.
- La séquence codée occupe \(21\) bits (\(24\) si chaque caractère était sur \(3\) bits, mais un
R
et deuxE
font chacun gagner un bit). - Donc pour cet exemple, le taux de compression est de \(64/21\) (à peu près = \(3\)).
Mais pour que le décodage soit possible, il faut fournir non seulement le texte codé
'101101100000100101111'
, mais aussi la correspondance entre caractères et codes ('E':11
,'R':10
, etc).Il faut donc stocker aussi cette correspondance dans le fichier compressé, ce qui dégrade le taux de compression. Néanmoins ce codage reste intéressant pour un texte long car dans ce cas la place mémoire occupée pour stocker la correspondance entre lettres et codes est négligeable devant la taille du texte compressé.
Note
Le sujet n’etait pas clair quant à savoir s’il fallait aussi transmettre la table de correspondance lors du calcul du taux de compression (sur ce message exemple
'RETUOOTE'
).
-
TP8.
q18
()[source]¶ Réponse à la question IV.1.18).
Le codage doit être injectif (deux textes distincts doivent être codés par des séquences de bits distinctes).
Voici une condition suffisante garantissant l’injectivité du code : il n’existe pas deux lettres
x1
etx2
telles que le code dex1
soit un préfixe du code dex2
.Note
On dit qu’un tel codage est un codage préfixe.
Le codage de
q16()
ne remplit pas cette condition (le code deE
est1
, préfixe du code10
deA
) et il est ambigu. Mais par contre, le codage deq17()
remplit cette condition (au moins pour les six lettres qu’on nous donne).Remarques: - La condition n’est pas nécessaire, par exemple le codage suivant
'A':1
,'B':10
,'C':100
ne la remplit pas, pourtant il est injectif. - la condition ci-dessus (codage préfixe) permet un décodage facile des séquences de bits.
- La condition n’est pas nécessaire, par exemple le codage suivant
-
TP8.
est_present
(x, cars)[source]¶ Fonction auxiliaire, qui renvoie
True
six
figure dans la listecars
,False
sinon.Note
En Python, on peut écrire directement
x in cars
. Ce n’est pas très clair de savoir si ce morceau de syntaxe est au programme ou pas.- Complexité en temps : en \(\mathcal{O}(n)\) ou
n = len(cars)
.
- Complexité en temps : en \(\mathcal{O}(n)\) ou
-
TP8.
caracteres_presents
(donnees)[source]¶ Réponse à la question IV.2.19).
On ne demandait pas une complexité particulièrement efficace. L’implémentation proposée à une complexité en temps en \(\mathcal{O}(n c)\) ou
n = len(donnees)
etc
est le nombre de caractères différents.Donc dans le pire des cas, on a un \(\mathcal{O}(n^2)\) (atteint pour une liste avec
n
caractères distincts). (En fait,n
peut devenir très grand, mais en ASCIIc
est<= 256
. En UTF-8 ou UTF-16, il y a beaucoup plus de caractères différents mais leur nombre reste borne).
-
TP8.
indice
(x, cars)[source]¶ Fonction auxiliaire, qui renvoie un indice
i
tel quecars[i] = x
et six
n’est pas présent dans cars, elle renvoie-1
.- Elle renvoie le plus petit
i
tel quecars[i] = x
.
Note
En Python, on peut écrire directement
cars.index(i)
. Ce n’est pas très clair de savoir si ce morceau de syntaxe est au programme ou pas... Notez que la méthodeindex
ne renvoie pas-1
en cas d’échec, elle renvoie une exception (ValueError
).- Complexité en temps : en \(\mathcal{O}(n)\) ou
n = len(cars)
.
- Elle renvoie le plus petit
-
TP8.
caracteres_frequences
(donnees)[source]¶ Réponse à la question IV.2.20).
On ne demandait pas une complexité particulièrement efficace. L’implémentation proposée a une complexité en temps en \(\mathcal{O}(n c)\) ou
n = len(donnees)
etc
est le nombre de caractères différents.
-
TP8.
q21
()[source]¶ Réponse à la question IV.2.21).
Exécution de
aux(cars, freq, 2, 7)
: on indique les valeurs des variables après chaque itération de la bouclewhile
(1ère ligne = état initial)k m cars freq 7 7 [' ', 'a', 'c', 't', 'e', 'è', 's', 'r'] [4, 6, 3, 4, 8, 1, 7, 4] (ini) 6 6 [' ', 'a', 'c', 't', 'e', 'è', 's', 'r'] [4, 6, 3, 4, 8, 1, 7, 4] (1e iter) 5 6 [' ', 'a', 'c', 't', 'e', 'è', 's', 'r'] [4, 6, 3, 4, 8, 1, 7, 4] (2e iter) 4 5 [' ', 'a', 'c', 't', 'è', 'e', 's', 'r'] [4, 6, 3, 4, 1, 8, 7, 4] 3 5 [' ', 'a', 'c', 't', 'è', 'e', 's', 'r'] [4, 6, 3, 4, 1, 8, 7, 4] 2 5 [' ', 'a', 'c', 't', 'è', 'e', 's', 'r'] [4, 6, 3, 4, 1, 8, 7, 4]
Après la sortie de la boucle, on échange les éléments d’indices
5
et7
, d’où l’état final des deux tableaux :[' ', 'a', 'c', 't', 'è', 'r', 's', 'e'], [4, 6, 3, 4, 1, 4, 7, 8]
et la valeur renvoyée est5
.
-
TP8.
q22
()[source]¶ Réponse à la question IV.2.22).
La fonction
aux
travaille sur le sous-tableau allant des indicesi
àj
(inclus).Il s’agit d’une fonction de partition (servant à effectuer un tri rapide), elle utilise comme
pivot
le dernier élément du sous-tableau :pivot = freq[j]
, et la partition se fait à partir de la droite (pas comme celle vue en TP, qui partait de la gauche).La fonction partitionne le tableau
freq[i:j+1] = [freq[i],...,freq[j]]
de façon à placer à gauche dupivot
les éléments<= pivot
et à droite les éléments> pivot
.
-
TP8.
q22_preuve
()[source]¶ Preuve formelle de la question IV.2.22) :
1. Terminaison : à chaque itération de la boucle
while
,k
diminue de1
donc la boucle termine en exactementj-i
itérations (on aurait aussi bien pu faire une bouclefor
).2. Correction (prouver que la fonction fait ce qu’on veut). Pour l’invariant : un dessin vaut mieux qu’un long discours
i k m j ----------------------------------------------------------- | ... | <= pivot | > pivot |p| -----------------------------------------------------------
(p désigne le pivot, les points de suspension les éléments pas encore examinés).
A la fin de chaque itération de la boucle
while
, on a l’invariant suivant :freq[r] <= pivot
pour tout indicer
tel quek <= r < m
,freq[r] > pivot
pour tout indicer
tel quem <= r < j
.
2.a. Cet invariant est vrai avant d’entrer dans la boucle
while
(les 2 conditions sont vides lorsquek = m = j
).2.b. Cet invariant est conservé par les itérations : on décrémente
k
de1
et on examinefreq[k]
(qui est alors l’élément le plus à droite de la zone contenant les points de suspension) : s’il est<= pivot
il n’y a rien à faire; s’il est> pivot
(i.e.freq[k] > freq[j]
), on l’échange avec l’élément le plus à droite de la zone <= pivot : pour cela on décrémentem
de1
et on effectue l’échange des éléments d’indices k et m. Ainsi l’invariant est maintenu. Victoire.2.c. En sortie de la boucle
while
, on a k = i, et on effectue l’échange du pivot avec l’élément d’indice m, afin de mettre le pivot à sa place définitive entre les 2 zonesi m j ----------------------------------------------------------- | <= pivot |p| > pivot | -----------------------------------------------------------
La fonction
aux
a donc bien réalisé la partition du sous tableau[freq[i],...,freq[j]]
autour du pivotp
.Quant au tableau
cars
, il est modifié en même temps quefreq
: chaque fois qu’on échange deux éléments defreq
, on échange les deux mêmes éléments decars
, afin de conserver la propriété (I) de correspondance entre les deux tableaux :- pour tout indice
r
,freq[r]
est le nombre d’occurrences decars[r]
dans le texte initial.
-
TP8.
q23
()[source]¶ Réponse à la question IV.2.23).
L’instruction suivante effectue le tri souhaité
tri(cars, freq, 0, len(cars)-1)
La fonction tri effectue le tri rapide (“quicksort”) à l’aide de la fonction de partition
aux()
(le tableau freq est trié en ordre croissant et le tableau cars est modifié au fur et à mesure afin de conserver la correspondance entre les deux tableaux, l’invariant (I) utilisé dans la fonction précédente).La complexité dans le pire cas du tri rapide est \(\mathcal{O(n^2)}\), où n est la longueur des tableaux considérés (mais en moyenne il est bien meilleur, en \(\mathcal{O(n \log(n))}\)).
Le tri par fusion a une complexité plus faible dans le pire cas : \(\mathcal{O(n \log(n))}\).
-
TP8.
insertion
(t, q, cars_ponderes)[source]¶ Réponse à la question IV.3.24).
On peut utiliser
cars_ponderes.insert(i, [t, q])
pour insérer la petite liste [t, q] à la positioni
, trouvée d’après ce que demande l’énoncéi = argmin cars_ponderes[i][1] < q, i >= 0
-
TP8.
numero
(x)[source]¶ On avait besoin de cette fonction auxiliaire, qui donne le numéro (un entier) associe au caractère
x
. On utilise la fonction Pythonord()
(fournie par défaut).- Exemples :
>>> print(numero('a')) 0 >>> print(numero('z')) 25
-
TP8.
codage
(cars, freq)[source]¶ Réponse à la question IV.3.25).
On peut vérifier l’exemple de l’énoncé :
>>> cars = ['f','b','d','a','c','e'] >>> freq = [1, 2, 3, 4, 4, 9] >>> print(codage(cars, freq)) ['110', '1001', '111', '101', '0', '1000']
-
TP8.
q26
()[source]¶ Réponse à la question IV.4.26).
C’était assez direct, une fois qu’on comprend ce qu’est l’ordre lexicographique :
‘0’ < ‘1000’ < ‘1001’ < ‘101’ < ‘110’ < ‘111’On peut vérifier avec Python :
>>> tab = ['110', '1001', '111', '101', '0', '1000'] >>> print(sorted(tab)) ['0', '1000', '1001', '101', '110', '111']
-
TP8.
q27
()[source]¶ Réponse à la question IV.4.27). Décodage de
txt_bin
='010100000011011101111011110'
.Voici le découpage
txt_bin = '010' + '10' + '000' + '001' + '10' + '1110' + '1111' + '011' + '110'
À savoir :
pos = 0
,m = 2
, code'010'
, lettre'b'
,pos = 3
,m = 4
, code'10'
, lettre'o'
,pos = 5
,m = 0
, code'000'
, lettre'n'
,pos = 8
,m = 1
, code'001'
, lettre'j'
,pos = 11
,m = 4
, code'10'
, lettre'o'
,pos = 13
,m = 6
, code'1110'
, lettre'u'
,pos = 17
,m = 7
, code'1111'
, lettre'r'
,pos = 21
,m = 3
, code'011'
, lettre' '
(espace),pos = 24
,m = 5
, code'110'
, lettre'!'
,
Le texte ayant été compressé était donc
'bonjour !'
.
-
TP8.
decode_car
(txt_bin, pos, code)[source]¶ Réponse à la question IV.4.24).
C’est exactement une recherche dichotomique dans un tableau trié (le tableau
code
), sauf qu’au lieu de manipuler des nombres ordonnés dans l’ordre usuel on manipule des chaînes de caractères, ordonnées par ordre lexicographique.Subtilité technique : les codes ayant des longueurs variables, au moment de tester si
code[m]
est présent dans la chaînetxt_bin
à la positionpos
, il faut extraire detxt_bin
une sous_chaine de longueur adéquate (la variablelongueur
sert à cela, cf. le code).Le nombre de comparaisons de chaînes est du même ordre de grandeur que le nombre d’itérations de la boucle
while
(il y a une ou deux comparaisons à chaque itération, dans leif
et leelif
), donc c’est en \(\mathcal{O}(\log n)\) oùn = len(code)
.Rappel de la preuve : À chaque itération on travaille dans le sous-tableau
code[g:d+1]
i.e.[code[g], ..., code[d]]
, de longueurd-g+1
; initialement la estn
, et à chaque itération cette longueur est au moins divisée par \(2\); dans le pire cas le nombre \(p\) d’itérations vérifie \(n \simeq 2^p\), soit \(p \simeq \log(n)\).
-
TP8.
decode_txt
(txt_bin, code, cars)[source]¶ Réponse à la question IV.4.29).
La dernière question n’était pas trop dure, en suivant à la lettre les consignes.
- Exemple :
>>> txt_bin = '010100000011011101111011110' >>> code = ['000', '001', '010', '011', '10', '110', '1110', '1111'] >>> cars = ['n', 'j', 'b', ' ', 'o', '!', 'u', 'r'] >>> decode_txt(txt_bin,code,cars) # On trouve comme au dessus 'bonjour !'
Sortie du script¶
$ python TP8.py
I. Reception des donnees.
II. Analyse des mesures.
III. Bases de donnees.
IV. Compression d'un fichier texte.
Test automatique de toutes les doctests ecrites dans la documentation (docstring) de chaque fonction :
Plus de details sur ces doctests peut etre trouve dans la documentation de Python:
https://docs.python.org/3/library/doctest.html (en anglais)
Le fichier Python se trouve ici : TP8.py
.