Aller au contenu

Codage de Huffman (encodage du texte)

Présentation rapide

Le codage de Huffman est un codage qui permet de compresser des données. Dans le cas d'un texte, codé en UTF-8, chaque caractère prendra la place de un à 4 octets. Dans le cas du codage de Huffman , plus un caractère est fréquent dans le texte, plus court sera son codage en binaire.

Exemple

Le texte : que voulez vous que je vous dise sera codé par : 01111011101110000011011000011010001111000001101010111011110111011110010110111000001101010111100110110010110. Soit \(107\) bits au lieu de \(256\) avec le codage UTF-8. Le caractère espace ' ' sera codé par 111, tandis que le caractère 'l' sera codé par 1 0000.

Série d'exercices

Cet exercice fait partie d'une série :

Les étapes sur un exemple

Prenons pour exemple le texte que voulez vous que je vous dise.

Le nombre d'occurrences de chaque lettre est :

q u e v o l z s j d i
2 5 5 6 3 3 1 1 3 1 1 1

L'arbre de Huffman est un arbre construit progressivement à partir des feuilles.

On commence par créer des nœuds pour tous les caractères. La donnée associée à chaque nœud est un caractère et son poids qui est son nombre d'occurrences.

graph TD
    N7(l:1):::feuille
    N8(z:1):::feuille
    N90(j:1):::feuille
    N10(d:1):::feuille
    N1(i:1):::feuille
    N11(q:2):::feuille
    N5(v:3):::feuille
    N6(o:3):::feuille
    N9(s:3):::feuille
    N2(u:5):::feuille
    N3(e:5):::feuille
    N4(_:6):::feuille
    classDef feuille fill:#F88
graph TD
    N22(( :32)) --> N20(( :12))
    N22 --> N21(( :20))
    N20 --> N16(( :6))
    N20 --> N17(( :6))
    N16 --> N5(v:3):::feuille
    N16 --> N6(o:3):::feuille
    N17 --> N9(s:3):::feuille
    N17 --> N14(( :3))
    N14 --> N1(i:1):::feuille
    N14 --> N11(q:2):::feuille
    N21 --> N18(( :9))
    N18 --> N15(( :4))
    N18 --> N2(u:5):::feuille
    N15 --> N12(( :2))
    N15 --> N13(( :2))
    N12 --> N7(l:1):::feuille
    N12 --> N8(z:1):::feuille
    N13 --> N90(j:1):::feuille
    N13 --> N10(d:1):::feuille
    N21 --> N19( :11)
    N19 --> N3(e:5):::feuille
    N19 --> N4(_:6):::feuille
    classDef feuille fill:#F88

On pourra trouver plus d'explications dans l'exercice sur la construction d'un arbre de Huffman.

Encodage⚓︎

Une fois l'arbre construit, il faut procéder à l'encodage du texte. On va créer un dictionnaire, dont les clés seront les caractères et les valeurs associées, le codage binaire du caractère en utilisant l'arbre construit.

La convention utilisée ici sera la suivante :

Dans l'arbre chaque embranchement à gauche correspond à 0 et chaque embranchement à droite correspond à 1.

Exemple d'arbre et de codes

On obtient l'arbre suivant :

graph TD
    N22(( :32)) --> |0| N20(( :12))
    N22 --> |1| N21(( :20))
    N20 --> |0| N16(( :6))
    N20 --> |1| N17(( :6))
    N16 --> |0| N5(v:3):::feuille
    N16 --> |1| N6(o:3):::feuille
    N17 --> |0| N9(s:3):::feuille
    N17 --> |1| N14(( :3))
    N14 --> |0| N1(i:1):::feuille
    N14 --> |1| N11(q:2):::feuille
    N21 --> |0| N18(( :9))
    N21 --> |1| N19( :11)
    N18 --> |0| N15(( :4))
    N18 --> |1| N2(u:5):::feuille
    N15 --> |0| N12(( :2))
    N15 --> |1| N13(( :2))
    N12 --> |0| N7(l:1):::feuille
    N12 --> |1| N8(z:1):::feuille
    N13 --> |0| N90(j:1):::feuille
    N13 --> |1| N10(d:1):::feuille
    N19 --> |0| N3(e:5):::feuille
    N19 --> |1| N4(_:6):::feuille
    classDef feuille fill:#F88

Plus un symbole est fréquent, plus il est proche de la racine.

graph TD
    N22(( :32)) --> |0| N20(( :12))
    N22 --> |1| N21(( :20))
    N20 --> |0| N16(( :6))
    N20 --> |1| N17(( :6))
    N16 --> |0| N5(v:3):::feuille
    N16 --> |1| N6(o:3):::feuille
    N17 --> |0| N9(s:3):::feuille
    N17 --> |1| N14(( :3))
    N14 --> |0| N1(i:1):::feuille
    N14 --> |1| N11(q:2):::feuille
    N21 --> |0| N18(( :9))
    N21 --> |1| N19( :11)
    N18 --> |0| N15(( :4))
    N18 --> |1| N2(u:5):::feuille
    N15 --> |0| N12(( :2))
    N15 --> |1| N13(( :2))
    N12 --> |0| N7(l:1):::feuille
    N12 --> |1| N8(z:1):::feuille
    N13 --> |0| N90(j:1):::feuille
    N13 --> |1| N10(d:1):::feuille
    N19 --> |0| N3(e:5):::feuille
    N19 --> |1| N4(_:6):::feuille
    N5 o-...-o N32[000]:::binaire
    N1 o-..-o N33[0110]:::binaire
    N4 o-...-o N30[111]:::binaire
    N7 o-.-o N31[1 0000]:::binaire
    classDef feuille fill:#F88
    classDef binaire fill:#FF0

Par exemple, l (peu fréquent) sera codé 1 0000 (5 bits) alors que l'espace (très fréquente) sera codée 111 (3 bits).

Note

Toutes les fonctions crées dans des questions, sont utilisables dans les questions suivantes.

Question 1 : lettre_binaire(arbre)

Principe : on parcourt récursivement l'arbre en profondeur. À chaque fois qu'on arrive sur un nœud,

  • si c'est une feuille, on met à jour le dictionnaire de codage
  • sinon on appelle récursivement le parcours en mettant à jour l'argument code en fonction du sous arbre gauche ou droit.

Compléter la fonction lettre_binaire qui prend comme paramètre un arbre de Huffman et qui renvoie un dictionnaire avec comme clé, les caractères et comme valeurs associées, le codage binaire du caractère.

Les étiquettes des nœuds de l'arbre sont des dictionnaire de la forme {"caractere":…, "poids":…}.

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.339.128013ev1wSrc7sq )_iRa:tà+4FUf3,o6[/hpmngP8y.{Nk5=ul;d92]}b0(050X0c0t0r0p0V0k0m0i0V0r0k0k0T010t0p0H010406050k0U0I0I0r0h0N040g0C0V0U0|0C0J0m020r0I0H0W0m0q0c160h0l0U0c0k050F13151719110H041x1E051H0F1H1J1E110X0p0d0;0?0^0`0G0p0K0G0V1X0G0t0 050,0$0V0c1S0@0_011W1Y1!1Y0t1*1,1(0t0$0C0X191)0h1F0t0G0;1c0k0H0r0J0`0Z011.1U010z0.0c0J1k0c1(292b2g1:2j1,2m0I2o040b0m0L0h0C0H0C0k0p1f1h0*270h0h0c0i2J1x2q0J1F0F252V0t2322240X2s0`1!0J2l2G1(1P1R0=1/2)0p2+0J1 1Q1(0H2O1F2T2V30122a1h2;2h2_0h160V0 0m0e2S3410332r361:383a3c0Z3f2b3h2T2(013m0r3b040m0A3q2U113t3k0`3w3y0m0w3C3s343u3I3c0S3M3E3O3G3v0C393x3c0D3T3i351T3l3Y3n3z0j3%3F3*3H3,3!3z0M3:3V3=3X3Z3J0Y3{3j3}3Q040e0%423)2=3~3-0e3e1y3g3U434b450e3p4g3r4i4a373@3y0e3B4o3D3(3P4t0 0e3L4x3N4j4s3 4C3S4F1G2~1x2/2Y0X2$3u0i1 2y0)1Q1F2}0c2 3g3M054V0*4%4H1:0R0 0*0z4)3;4b0f3c4@3|4k0z0 1,1_2O0o0$2@0-2O4|4.0`0~040(594r3l0 170$584M4^2h5c0B3M0m4z3W0J0 4+0r0K0c5f3u0C0 0T5B3W0k2e0401015G3}5p5r5t445w1 5y1v0o3x0H0G0r0$0+5r5s5n1:5D045F5m4}2h0R0i0 0Q1g5A5/5a015c0n0s3T0m625)5:4/0 0p4?4F645|5v045x5z0k5X0V5Z5#5%6a6b5g0`5,0T5.306o3u5=5@5_5Q5*6q4`042b0X6A653H5i0h5k5`326B015,0O5N4k0 1v0t0o0z0c0U0.1,6T5o0 0(5 61636.5R6U6e170r2Q0c5l6u6:2h6r6H6c6K6M6(5+0 6S5{6p3v4;1g2+6N4(6P5c6+0E730`5I0 010i6?6^2O5M773u5c0!6-6.626|66042O0t0U0h0J6 785c0P7j796=0h6@0t6_7d3r7A5b0 607t5H0e0 000%007M5c0#7x6v3W4:04687I3P5T0X5V6h5Y5!5$0t5(7V6Q5E6t3g7.3}6x045^2+7*7X7-6/6P6d6f5W7|6l7 6n816~7Z5O0 0P7,4F068f6I017:7=6a816d5j6`7e8y6R7M6d6W6Y6!6$7T2U817g6,8v7y638D5w7p7R8G3r864b8p6{8g718$8R6P8J8q6;0X7b0c8Q4-7J6*0n7i8=2h7l5K7o7P7q2o8c047w8V8W8(377^7`6i6k7~7?3W5c8 6O8y8h8!7S989a8+8I5E9k5S6e5U5z7-817:0c0/8`8S8d9b8W8Y040K0r0U0i0G8`9d745-9y6;8F9I8:758K0 0k0C0U7{6L539P9R9T986+8e8X8,040X2D2I9Y6}9x8C9`9!7M8;9o70049*9,5X9.0c0o9|0C9~901:8T9^7z9`512Zae552m0p8.8{7u6*9(9O9Q9S9#8y5Pa29p9f9CaG5|5,0v9 1:92010%7sa78|045qaj6J9A7_6g9h7}6m9v5|5~am9VaZap53as57aDa+ayaY7NagaiaUaxaWaOaZ8ib18204aNaK78aQ7#98aXa~5uaI8j6ja(8ma*aV0n9D6P7:7D7F7Hb87@a!9g8k9j6a110F4+4$4NbE0F4Q1x0t4SbJ2!2W1~202Y5#1,2V4Q1Daw3W2O0I6Y0r0Rae0G0A0 1p1r1t1v0m7Y321K3h1E0y2+0m0d6_2H1g0m0rb|0i0m0U1h2a0h4V7F0:2l0m0?0h5z7F0B0m1t0p0m0p1l1!b.0m0X002l2u6_cd1-bD277F2b0tc0c2cx0:0z1eca0m0J0a0U0X0:0ub{0p2H8#761N4Y2:3}1=1Z1#1%bX3}cv2w2y2A0g0i0h0}cD0L0N251g4)4#8{314(bDc)4b7:4=7M6D5sa`0J4 04a:ar56aua@aV5ed88-dga 8U308w9_aHbwa$bya)85a.b5848%9J048tbodrb3bu3W8*8581aQaT4h8x5|8A69blbva4a`a68Ha88M6Z6#0V6%a`8Tb;dO9c9N947Q9sdH3}dJdAa3ada59%dj9{8^dl9l8}9ndYb95J7n9r7r9ta-9E0 br7Gb47Kazd/9698d+7U6P0k7#047%7)d)0 8udodP786dcvb4d@2Udx6d0x2k9?bn9LeF0 eBdWd|be9zcueIeu5ddieR9Zd`eVbddK9`dGeY6)040neKexdqdQ0 0f1Wd(dTdI6D2_bke%dreOe*9W76f1aZ8M0d0p0*eJem3D9ceM7C6@2@e08rb0d}e)e~aLa1e_9zf0e45CeQftbf9{0cfsenaE8}ebbp67dSfnezedfg8beP04f3fweS0k6Xd#8Pfaa-eybvej8#9U8ofpfIbv95fhd{fOaz8@0J7ceJe3fB5|aQf!7SdNf^aV9ud,fdandF9Bbh9idvd^fC04f@8/dFe8fi4b7veCf(g9a8fm4pfdec049G0kgge+fb10g2e:fJaA9;f$9$9Xd=6;f+fMf4b5fPf~bvaa9-6M0o9:aCeJfXgzbva|e}gl78eD3z9NgIguf2azgPacgRgZgVeLgp9`fAgdfof.d}eTe^fQgh6*eXh09egBgUe#b48hg5gjb6b4aQaS98e-gWg3a8g_d1a0g|gK8Ld9eUgK7gh3gNfxg;h8gGh5gneEf%hdhBaPe6bbeVhieLgqeebtfq6;8i7{bi8l3%bC4W2Vc|4P4ZbB0*0,0.0k04.
Question 2 : encode_texte_codage(texte, codage)

Il faut maintenant encoder le texte initial avec ce code obtenu.

Créer la fonction encode_texte_codage qui prend comme paramètre un texte et qui renvoie une chaîne de caractères contenant le codage binaire du texte.

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.128013ev1wSrcs )_ia:tj4f3,o[/hpmngP.yxk5=uld2]b(050M0b0p0n0m0L0i0j0h0L0n0i0i0J010p0m0z010406050i0K0A0A0n0g0F040f0v0L0K0+0v0B050x0=0@0_0{0:0z04141b051e0x1e1g1b0:0M0m0c0Z0#0%0)0y0m0C0y0L1u0y0p0.050U0P0L0b1p0$0(011t1v1x1v0p1D1F1B0p0P0v0M0{1C0g1c0p0y0Z0~0i0z0n0B0)0N011H1r010s0W0b0B0n0A0b1B1)1+1:1J1?1F1_1{0.0a0j0D0g0v0z0v0i0m110B0j0S1%0g0g0b0h2g141~0B1c0x1#2t0p1Z1Y1!0M200)1x0B1^2d1B1m1o0!1I2D0m2F0B1V1n1B0z2m1c2r2t2X0;1*2h2L1;2Q0g0^0L0.0d2q2#0/2!1 2%1J2)2+0.0N2/1+2;2r2C012_0n2,040t2}2s0:302@0)33350r382 2#313e0.0I3h1d2V142J2w0M2A310h1V1|1c3s1f3q2Z152:053x0S2W3j3c010H0.0S0s3o3b1q1J0e0.0j3S3L3U3d0s0.1^3I0b0l0p0b0G3-0l3I0n0C0b3Z2?3#010-040Q3_2$3{0B0.3-3/3^3F2~2=412M3|0.0u3h3Y3T4c43043=3@0i0l340z0y0n0P0T40313}0k0o3h060j4D4h3!4j443.3:3*4g4a310v0.0J4M4i2(0P0.1x0i0p4w3M3}0Q0k4B4E4F3`4c3O040s0v0g4S4G2(0.0h0_0n2o0b2m4?4,1;0v3W042O504b4^04453-4!3{3}4A48394*4*4N3M4k5b3+4L5h3K511J4P040E5d4H040n0z0z1^0M5y1;4$5G2^4_1V3?0b4o4q4s4u4Z5r5l5e0.0w5J3d4_4{4}4 5U4T1J3}0O4(5r4C4E5V4-0.2m0p0K0g135r4+581J0i1.0401015Z015v5x5)4@5K040q0v566a5t0)5I6h5 5!5a4J5p3y664y4B143*2t2U0b2t3B2u3u142x2w1U1W2w4t1F6A1n2;0x0S0U0W0i04.
Question 3 : encode_Huffman(texte)

Pour encoder un texte, en utilisant le codage de Huffman, il faut :

  • créer l'arbre de Huffman à partir du texte. La fonction arbre_Huffman(chaine) est intégré à l'IDE,
  • en déduire le dictionnaire de codage
  • encoder le texte.

Compléter la fonction encode_Huffman(texte), qui prend en paramètre une chaine de caractères, et renvoie une chaine de caractère, représentant un codage de Huffman du paramètre.

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.128013ev1wSrcs )_ia:t4f3,o/hpmngPyxk5=uldH2b(050J0b0p0n0m0I0i0j0h0I0n0i0i0G010p0m0x010406050i0H0y0y0n0g0C040f0u0I0H0(0u0z050v0/0;0?0^0-0x041118051b0v1b1d180-0J0m0c0W0Y0!0$0w0m0A0w0I1r0w0p0+050R0M0I0b1m0Z0#011q1s1u1s0p1A1C1y0p0M0u0J0^1z0g190p0w0W0{0i0x0n0z0$0L011E1o010r0T0b0z0n0y0b1y1$1(1-1G1:1C1?1^0+0a0j0B0g0u0x0u0i0m0~0z0j0P1!0g0g0b0h2d111{0z190v1Y2q0p1W1V1X0J1}0$1u0z1=2a1y1j1l0X1F2A0m2C0z1S1k1y0x2j192o2q2U0.1%2e2I1.2N0g0=0I0+0d2n2Y0,2X1|2!1G2$2(0+0L2,1(2.2o2z012?0n2)040s2`2p0-2}2;0$30320q352|2Y2~3b0+0F3e1a2S112G2t0J2x2~0h1S1_193p1c3n2W122-053u0P2T3g39010E0+0P0r3l381n1G0e0+0j3P3I3R3a0r0+1=3F0b0l0K0H0r0r0=103C2{2/2Z3Y010*040N3W2:3@0z0+0h0w0S2C3|3?2J3^0+0k0o3e060j4e3V3Q473 040?0M2j3e4g3X470u0+0G4o3=3h0+4l2j3)3+3-1(452~3_3{3:2p4w3J4j41430b4F3J3_0k4c4f4p3}4i3M0m3u0l3$1S0n0A4Q4J044X461.4s044u4-4/4x041C1M4A0M2L0S4n4-4L3@4H4R3~4y0g4m4,2W4h1.4T4V4f544Z044O2L3(4(0P5c2-4_3J4=4@2U5t58045p3(0p0b0D5D0l3F4*5r3;5e1G56535M3a40425n57473_0t4v5Q2 4!4$5p5J5V5f495h4e5j1.3L042j0p0H0g3/5x5/2=5S4P4%0z3%5K36113%2q2R0b2q3y2r3r112u2t1R1T2t0n1B693o1k2.0v0P0R0T0i04.

Remarques

  1. Pour l'exercice le codage est « textualisé », alors que, dans la réalité, l'opération se passe au niveau des octets et est donc plus difficilement visible.
  2. En pratique, le dictionnaire de codage est transmis dans le fichier avec le texte à décoder.