Skip to content
Snippets Groups Projects
Verified Commit c39d1d34 authored by iliya.saroukha's avatar iliya.saroukha :first_quarter_moon:
Browse files

feat: report finished

parent d0557710
No related branches found
No related tags found
No related merge requests found
......@@ -420,4 +420,176 @@ Node(weight=9,
Pour le décodage, nous allons appliquer l'algorithme présenté dans le cours
n°5. Celui-ci stripule qu'il est nécessaire de parcourir l'arbre au fur et à
mésure jusqu'à retrouver la feuille NYT. À ce moment il est
mésure jusqu'à retrouver la feuille NYT. À ce moment, il est nécessaire de
lire les $e$ bits suivants. Si la valeur de ceux-ci en base 10 est inférieur
à $r$, alors pour obtenir le symbole correspondant il est nécessaire de lire
les $(e + 1)$, de les convertir en base 10 et d'y ajouter 1. La valeur numérique
résultante sera la position dans du symbole dans l'alphabet. Si la valeur de
$e$ est inférieur ou égale à $r$, il faut convertir ces bits en base 10 et d'y
ajouter la valeur $r + 1$.
Plus concrètement, nous allons en premier lieu nous débarasser des éventuels
espaces dans la chaîne de caractères codées, puis nous allons lire cette chaîne
jusqu'à l'épuisement des bits dans celles-ci. À l'intérieur de la boucle, nous
commencerons par parcourir l'arbre jusqu'à la feuille NYT. Si la valeur du bit
actuel est 0, nous allons bifurquer à gauche, sinon à droite. Ayant recontré
la feuille NYT, nous appliquerons l'algorithme énoncé précédemment pour
déterminer le caractère rencontré. Celui-ci, sera rajouté à la chaîne de
caractère finale et sera aussi insérer dans un `set` afin d'indiquer que ce
caractère fut recontré. Ceci est important du fait que lorsque ce caractère
sera à nouveau rencontré, le parcours de l'arbre ne se fera plus jusqu'à une
feuille NYT et par conséquent le code NYT ne sera plus présent dans la chaîne
décodée. Ce cas est présenté par le branchement conditionnel à la ligne 43.
L'implémentation de cette fonction se trouve ci-dessous :
```python
def decode(encoded: str) -> (str, str):
bits = encoded.replace(' ', '')
tree = Node()
result = ''
seen = set()
i = 0
message_with_nyt: list[str] = []
message_without_nyt: list[str] = []
while i < len(bits):
node = tree
while node.left or node.right:
if bits[i] == '0':
node = node.left
else:
node = node.right
i += 1
if node.value == 'NYT':
e, r = compute_vitter_params(len(LIST_ALPHABET))
prefix_bits = bits[i:i+e]
val = int(prefix_bits, 2)
if val < r:
code_bits = bits[i:i+e+1]
k = int(code_bits, 2) + 1
i += e + 1
else:
k = val + r + 1
i += e
char = LIST_ALPHABET[k - 1]
result += char
seen.add(char)
insert_char(tree, char)
message_with_nyt.append('NYT')
message_with_nyt.append(char)
message_without_nyt.append(char)
else:
char = node.value
result += char
insert_char(tree, char)
message_with_nyt.append(char)
message_without_nyt.append(char)
pprint.pp(tree)
pprint.pp(tree)
return ' '.join(message_with_nyt[1:]), ''.join(message_without_nyt)
```
### Résultat du décodage
Pour la chaîne de caractères encodées `Code final: 000011 0 000000 00 01101 100
00110 1100 10001 10 0 11100 01010 110`, nous allons à nouveau obtenir la
chaîne initiale "darkvador" tout en reconstruisant l'arbre au fur et à mesure
du décodage.
```bash
Message initial avec NYT : d NYT a NYT r NYT k NYT v a d NYT o r
Message initial sans NYT : darkvador
```
L'arbre résultant de ce décodage sera donc le même que celui construit au moment
de l'encodage :
```bash
Node(weight=9,
nyt_code=None,
value='NYT',
left=Node(weight=2, nyt_code='', value='d', left=None, right=None),
right=Node(weight=7,
nyt_code=None,
value='NYT',
left=Node(weight=2,
nyt_code='0',
value='a',
left=None,
right=None),
right=Node(weight=5,
nyt_code=None,
value='NYT',
left=Node(weight=2,
nyt_code='00',
value='r',
left=None,
right=None),
right=Node(weight=3,
nyt_code=None,
value='NYT',
left=Node(weight=1,
nyt_code='100',
value='k',
left=None,
right=None),
right=Node(weight=2,
nyt_code=None,
value='NYT',
left=Node(weight=1,
nyt_code=None,
value='NYT',
left=Node(weight=0,
nyt_code=None,
value='NYT',
left=None,
right=None),
right=Node(weight=1,
nyt_code='11100',
value='o',
left=None,
right=None)),
right=Node(weight=1,
nyt_code='1100',
value='v',
left=None,
right=None))))))
```
\newpage
## Utilisation du programme
Le programme `dyn_huffman.py` est utilisé de la manière suivante :
- Si l'on souhaite encoder une chaîne de caractère, il est nécessaire de
la préfixer du flag `-e` (pour _encode_) avant de la fournir à la ligne de
commande comme ceci :
```bash
python3 dyn_huffman.py -e "darkvador"
```
- Inversement, si l'on souhaite décoder une chaîne binaire il est nécessaire
de spécifier le _flag_ `-d``(pour _decode_)
```bash
python3 dyn_huffman.py -d "000011 0 000000 00 01101 100 00110 1100 10001 10 0 \
11100 01010 110"
```
## Résumé du travail
Ce travail pratique nous a permis de mettre en œuvre l'algorithme d'Huffman
adaptatif pour la compression optimale de chaîne de caractères. C'est avec un
franc succès que nous avons réussi à encoder correctement une chaîne de
caractères fournies en argument au programme grâce à la construction itérative
de l'arbre binaire, puis implémenter le décodage associé afin de retrouver la
chaîne de caractère initiale.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment