Aller au contenu

Hachage par XOR et LZ78

Méthode de Compression en Hachage⚓︎

La méthode de compression consiste à utiliser tous les bits de la représentation de données, que l'on découpe en sous-mots d'un nombre égal de bits, et à les combiner à l'aide de l'opérateur XOR. Cet opérateur a l'avantage de maintenir l'équilibre des valeurs (en évitant de rendre les résultats systématiquement plus petits ou plus grands).

Dans cet exemple, nous allons utiliser des sous-mots de 5 bits pour effectuer les opérations de compression.

Chaque lettre de l'alphabet est encodée par sa position dans l'alphabet

lettre position code 5 bits
A 1 00001
N 14 01110

L'espace est encodé 27 : 11011

La table suivante illustre le calcul des hachages pour différents mots en utilisant l'opérateur XOR.

Table de Compression⚓︎

Mot 1er Sous-mot (5 bits) 2e Sous-mot (5 bits) 3e Sous-mot (5 bits) 4e Sous-mot (5 bits) Résultat (5 bits)
NAT 01110 00001 10100 11011 11111 (27 en décimal)
CARO 00011 00001 10010 01111 11111 (31 en décimal)
REDA 10010 00101 00100 00001 10010 (18 en décimal)
KRIS 01011 10010 01001 10011 00011 (3 en décimal)

Explication des Calculs⚓︎

  1. Mot "NAT" :
  2. 1er sous-mot: 01110
  3. 2e sous-mot: 00001
  4. 3e sous-mot: 10100
  5. 4e sous-mot: 11011
  6. Calcul : 01110 XOR 00001 XOR 10100 XOR 11011 = 11111 (En décimal, cela donne 27)

  7. Mot "CARO" :

  8. 1er sous-mot: 00011
  9. 2e sous-mot: 00001
  10. 3e sous-mot: 10010
  11. 4e sous-mot: 01111
  12. Calcul : 00011 XOR 00001 XOR 10010 XOR 01111 = 11111 (En décimal, cela donne 31)

  13. Mot "REDA" :

  14. 1er sous-mot: 10010
  15. 2e sous-mot: 00101
  16. 3e sous-mot: 00100
  17. 4e sous-mot: 00001
  18. Calcul : 10010 XOR 00101 XOR 00100 XOR 00001 = 10010 (En décimal, cela donne 18)

  19. Mot "KRIS" :

  20. 1er sous-mot: 01011
  21. 2e sous-mot: 10010
  22. 3e sous-mot: 01001
  23. 4e sous-mot: 10011
  24. Calcul : 01011 XOR 10010 XOR 01001 XOR 10011 = 00011 (En décimal, cela donne 3)

Résumé⚓︎

La méthode de compression par XOR permet de "réduire" une séquence de bits en un seul nombre en combinant les sous-mots. Cette technique est utile dans les algorithmes de hachage, où chaque entrée de taille variable est condensée en une valeur de taille fixe (ici 5 bits).


Table avec les valeurs en 8 bits et 32 bits⚓︎

En 8 bits⚓︎

Si l'on adapte cette méthode pour des sous-mots de 8 bits, les mêmes principes de fonctionnement s'appliquent, mais avec une plus grande capacité pour chaque sous-mot, ce qui peut influencer le résultat global du hachage.

En 32 bits⚓︎

Si l'on utilise des sous-mots de 32 bits, la même technique serait mise en œuvre mais avec une plus grande précision pour chaque élément de la séquence. Cela permettrait de gérer des ensembles de données beaucoup plus volumineux tout en conservant une structure cohérente pour l'opération de compression.

Ecrire une fonction pyhton qui retourne le hachage sur 32 bits d'un texte avec la méthode précédente.⚓︎

La répartition de cette méthode de hachage paraît-elle uniforme ?⚓︎

Algorithme LZ78⚓︎

Je vous conseille de lire cette page.

Principe :⚓︎

– On a un dictionnaire qu’on met à jour progressivement – À chaque étape, on cherche le plus cours mot non présent dans le dictionnaire. – On écrit la position du mot trouvé, ainsi que la lettre à ajouter (10,r) – On écrit le nouveau mot dans le dictionnaire. – Et on continue à partir de la suite

Exemple⚓︎

texte = 'theoreme de parseval'

Construction du dictionnaire :

theoreme de parseval

Index Préfixe
0 ''
1 t
2 h
3 e
4 o
5 r
6 em
7 e
8 d
9 e p
10 a
11 rs
12 ev
13 al

sortie :[(0, 't'),(0, 'h'),(0, 'e'),(0, 'o'),(0, 'r'),(3, 'm'),(3, ' '),(0, 'd'),(7, 'p'),(0, 'a'),(5, 's'),(3, 'v'),(10, 'l')]

Reconstruire le texte à partir de sortie⚓︎

Le dictionnaire est construit dans l'aure sens Préfixe, Index.

Important On obtient le même dictionnaire en inversant clé et valeur. Cela permet de se passer de l'indication du dictionnaire dans le fichier compressé.

entrée : [(0, 't'),(0, 'h'),(0, 'e'),(0, 'o'),(0, 'r'),(3, 'm'),(3, ' '),(0, 'd'),(7, 'p'),(0, 'a'),(5, 's'),(3, 'v'),(10, 'l')]

Index Préfixe
'' 0
t 1
h 2
... ..

sortie : 'theoreme de parseval'

Complète le code suivant pour implémenter en Python les fonctions compress et decompress avec l'algorithme LZ78⚓︎

###(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 : 5/5
.128013ita;,Fnî2R7+14 fj08}elor=[à]/m3dv{T.S5éwbcyqA:-up)_9hxPès6(gk050G0v0c0d0b0w0)0p0Q0w0d0)0)0z010c0b0X010406050)0W0E0E0d0y0R040L0x0w0W110x0h050D181a1c1e160X04051u1n1x0D1u160G0b0H0_0{0}0 0{0h0,0W0d0,0v0V0X0R0c0#1l0p0#0b0,0#0w1Z0#0c14050;0P0w0v1G0|0~011Y1!1$1!0c1,1.1*0c0y1v1U0_1h0)0X0d0h0 0j011:1I010q0?0v0h0d0E0v1*25272c1=2f1.2i2k140a0p0%0y0x0X0x0)0b1k0h0p0/230y0y0v0Q2F1n2n0h1v0D1U2S1 21201+0G2p1J0b0h2h2C1*1D1F0`1;2$2(0h0x2,1*0X2L1v2Q2S2|17262G2.2d2=0y1b0w1*0d1X2L0q0 030Z0Z0Q2?0v1$2;0x0V0s0V0n140p0n1n0d2}30152 2o321=3436383a0v3c013e3g3i3k2)3n0V2a040p0j3u3w273y2Q2#013D0d371v390#3b3d3f3h0/3N2=3P0F3r0F3V2P3x163Z3B0 3$3(053*3,3J3.3M2%3O3o0o3r0o3`1o3|3z311H3C0x353%3F3+3H3-3L3:493=3o0M3r0M4f2|3}303!414p453K3/3j4v3m3o0*3r0*4B4h3~4k404m3E3)3G3I4J483l3P0l3r0l4S3X4D3A4V3#4X4o4Z4q4#474u4(3o0t3r0t4-2R4/4j2/4=4n42444r464t4L4}0V0!3r0!523Y4E3 574Y434!4s4K3;4N3p0s140n0s5k544F4?595r5c5t4M3P0n3q045L5B4i5D584H5b4$4|4a3p3R0n3U0D3v3{4.5Q5n4G4^4I4{5e5X0n3@5N3_5$3W535*4;5,5q4_5s4%5;4c5N4e5_5(5{4U565~5a4`5d5u5K4y5N4A674g5)6a335E5T6e5I5f0n4P5N4R6l4C5|6b6q5-5U5/6g3o0n4*5N4,6z4T5m5}6D5 5.6f5J6I4 5N516N6n6P6C5S6E6s624w3p5h5N5j6!696$6p6(6S6F6U5f0j5x046}5P6o4l6^6d615W6,0j5M79716?735p755H6+5v0j3R7k7c4:6%7f5G5V5:785?0j5^5%6m6=7o6@7q607h777j640j667y6A724W747r6G6V3Q6i0j6k7L6O7B7e4@6_6*7G3P0j6w7*7n557C7#7g7s6H3Q6K0j6M7X6#7Z7O7D6T6t5X0j6X837-5R7 6`81786.0j6:7{7A7.7!5F7E7=7S0F6~8n865+6R7;7R5f0F5M8w8q6Q7P8k8u5X0F3R8F8z7p7:7Q6{8E5?0F7x5`5l7}5o8K8C8M6,0F648Z8I7/8j807i3?6i0F7W8R5C8r8B8)7(3o0F6w8_8$8i6r767t5v0F6K928|7~8V8?903?6X0F6Z8f8S8h968(898*8^6.0F8e8/6B8%8~7F994b6~0o5A6;9f87979j8@0V0o5M9G958U9i7%9u9F3R0o5#9e8:8A889M7?0o5?9Y9J6c8L8a5v0o649*9#8s9%9k9F6i0o8.682S2_0v2S2,2V0G212!5n4K2+1E1v9`2{3x9^054Ka82o0b0G0 3f2Q5K3Fafah8X5v3q0p2t0van9(ak2S5%7N010-140/0qaaaz0O3raF7d400q143h0E9`0}aJ8T13040+aS9g3#140c0v0$a#aX3!aU0Y0U9^167zad2Gam01ai307)alaga@aoa`ar2jata}av3o3R3V0pb80p9q3CaN0W2K2h0c9^baaz0x140zbibb0 0)5M02039n0ebtbva.a)a?a^273?a{au9:3@b02kbG9E5?b7b9bpaZ040;0?1.1D2NbobkbmbYaK010E0b149y6Aa:5QbB0Zaj4bbFb39:4cbJb28D6,64bOb8bQ0haC0d0;0Qb#8Tbl04bna:bjb$aU0A0Cbzb-3Zb/b;0V6i5qb/b4cn2basbL9Nco5_b9cd8Tc204bW2F2i0b2Lc7aYc9cb2|cAaYaU0Ia)5nbr14bx0!bwbucXcS4;aUa-ccbQb(b*c#56aU0uci2~cka|bC0h3P6wcpc@a~4Octb1cv7?c{cybPazaB040q4mcJ4FaNdc5n0xaH042%df5}a!a$a(cjce14c(b,c=4Ecla_3o6Kc|d27S4*b`dC5fdAd5czc0d7140baEc)azaUaWdqcBbdbf0hbhdUcK140mc-33ded!a*140Ydl56dhdN1mdQb$cCcE0b1lcGcId+5nc%c;a9c?ancm6XdBb@9E4 dFe99Ne7dJdKczc1dW2LdYd(1=c90mcMe3d^d*duesaec}cm6.e8b|5v5heceC3PeAegeidM043j0)0ven0 e1a:a/dvexe5dy5wb?eG6I5xeFc~eZax3SehdKejcDc40dc6d 4;c90KeQbR0d0X0X2h0Ge{dSdTeVaYd_0b2Nd{0hd}ePe@c.140Ae{cC0QbeeldZf5d,040C0fd/d)04e?foe0d-d.d@8T0Q5M030p0d0r0x1j2H0W230W0X1.0p0+0cfO1.0Y0p0H3%0vbe2H270^d`d|0=2L0f0_1ce=0c0(2L0p18e~0w0N2kdYf+fdev3Xb.eyeY5Le!e)g5e(crg5e+e-e.azcCbT0wbVf8fn3xcO3!eper3Xgn5nc+5Ne2g1e4a}cm5!g6ga2ag99:gBgcgdd6etcDgkfafcf2fgfiekbgfteod$gSfvgQfqgV0 cLg$bRghgjbXccgs4;fD14fFfHfJ0c2HcW0e0W2(arfJ0H3jfQbg0y0N1/0Gf%0pfQf)fbf~gw2Rg2eXbD6IbN39cqgGbIcued7?5=1*eJe-e/fkdXglgrbQg(fBaYcU04g{g{g)g;04fF0k0:fJ0y0p0Bha390Q0#0d0ig~0Haff 4hd+dxhj3pb~hmc}gab_hqe#h,hu3veKb$d82LfT0yd?cNe/h8c5hfa;0ph*c_6Icoh.dG5;4ygF9E0ncx3veUewa=g3h+6vgCgG4Pig9Niqe+ilgxdwioi93pdAichr7S6Jd0bKiG6udIayb$hL03fF0Th10QhU0p2_0beO0p2h23aPa#2H1/0{0p2f2G2Ia#a%1/bg0bf=0vf|g_h80h0^hbgNf*cHh%5)h)iB5Ke7iFh?0nebh=g7efiO8Td8aDe{dibafe33aMfv0xaP2LaRjo1=dSgYi;dpfxc$d-dth(foi85KeAjag7eEjegaeIh_gKdVfvflgUhEgob!jXcTbscZcYbyeTbAj7b56~eBe)6}iJb{j:j.ege/g+0vcEg)hDi1azgub+jGimi7j,3Q5Mj/cr79j=id78k9j_gfc3i4j!e^jZk0dr04cgi5hhgzeY7kir9Ekwiu7?kwgIdLgLhcgPkld:kngmbQcQe{hGhIj%g!jFhBk1b)04k3izaT14c:j*j6hiiC7wkx9Nk+kA7Sk+kDg/56d8da0yg)fjj~didkkIfujAj4hgdRdsksgyc^7)h-k6ke7HkdiL82b~hvkEjidNdPkok!aVgYhyfme{eplrg!fAlocKk~i0kLkigMf9j2d~jCff04kT5{k(kuh+7Vk,kBifjO9:lRk=gdhxjVemjwg%d$gql4gLfwk4kZink)7)c{jLkbitlVkyd4jRgJk?fu0q0{0,j~kKkUh{0Q140J0y0Wl33ylOl9b5iElclg78dEl`k-iNe,ehbQd8eNmdkMl6k%jHk783lSk:jdd1mk7jjgmqgJi2e;l-l/jY04e`l%e|e~f0g!0+f4k55+aCj1hdj3g!fhmSfjl#hAl+lpfrk{eumZjD040YlylDiPfEfGfIfK0GfM3hfU1/fSn5fWfY1.f#i}f(m$fcf-0Qf/2Ni_f@fOfPf{bghemyk5jIb5jKmjh?8dlfnyjQmJlZlEj{j}l0gW04eqg)gu3tnsmOnu0V8nmC8ve%mn7?nTlYhwlEkGnrlJ2dcflrm-m4nKlwmSaUchnIl(cam=bS0=gij|gkbil 1=iQm g^g`j%g}1/2=0Wh1n}i#dYh5h7h9j0lGm%lIl.m/l:lPiC8wnU8EaqnX8mkgl}mKlElsjWlzmPl*3SbQkPj%hJn@01o3hO0chQhSiWhWhYh!h$l7iAl;8^b6l@bHgEow8vb6ljgegLm11On.oGo10 0-m8040g3%eOoYeWoq3?hlnxe)8PnAp5bNkhh{lmn`o:m3n;mxg0oop4cm8Zot8Yh;mFh?pmn!lkf6kje=lu14mRn)bc04e}e 0hf1pgaVmYmOm!lFcFn(m@lKm*pB40gTl$pT01n=fsoMoJbvoLpXa+m{j5mzo!nSibp4cr8-p7p=ijmJms14h}belCm6jTi3pxnPpjnR8_pn91l_pqp5l|mep-p18^mihnbMmmqbp=mpp{cD3HjlaIm+jq0/aOaQ0)mWgYq2mNpjfym_lMqentk79cq89ap@bHmIh`q1nfpPq0d#n_oMkNmSk2kSg)p$cXp(pQn*k#hKm~1W2%h10yi!fQeOi~1G0N0Vnaf!hR2Bf#2DaP1$2f0vhR1.0^2LhWr7rcqzq4i6q6nwqj9N9nqObMnCqRpvbSdomdo@01j m|8T0)3R020S0W0x0cbwrDrF0eo opmg9Fj.o%9E9xrn9NrSk=j`n|g,m.oHbZqXoEgtkWkYlNqfrN9GqM4bovqmb^oyp`eLk_n`2%0/0$g!p!r(dmfvnja#omqVgolBn`qCq$rgktr.o$p;b^o)r?rRo,ozrqddrsi=n.nLoMf7okkHp)gRm+d=r~g!n?s2kJn/svaNs5r7mdiyq5k79Yr:9FhpslrUp9sojSrrnGn oMgpnMkWnOpirhsQlbrk9XppiKh?9*h^nDsZsqn%m(pIpSq+pCs#g-szg#s%m52Rpus|qTs~t5t0pLs3r}a$sEstn`ni0yf:sMrLpkeY9?sStuk/5fturWeLp}h n`l2ks0Dac1y2`1n9}1n0c9 tN2Y2T0d1-9{tLa5a/0/gh0)04.

Remarque : Le code présenté ne tient pas compte d'une situation particulière où la toute fin du texte contient un préfixe entièrement dans le dictionnaire.

Dans ce cas, on ajoute simplement le couple (prefixe, '') Ă  datac.

  • adapter le code pour prendre en compte cette situation.

Remarque 2 : Il est aussi possible d'adapter le code pour imposer une taille de dictionnaire maximale.

Version avec taille de dictionnaire limitée

```python def compress(texte): current = '' tailledict = 0 datac = [] dictionnaire = {'': 0} taille_max = 10 for c in texte: if (current+c) in dictionnaire: current+=c flag = True else: datac.append((dictionnaire[current], c)) # ajout du couple (tuple) valeur dans dictionnaire, caractère supplémentaire tailledict += 1 if tailledict < taille_max: dictionnaire[current +c] = tailledict # ajout d'une nouvelle entrée dans le dictionnaire flag = False current = '' # Retour à la chaîne vide if flag: datac.append((dictionnaire[current], '')) return datac

def decompress(datac): dictionnaire = {0: ''} # on inverse le sens clé-valeur pour simplifier les recherches texte = "" tailledict = 0 taille_max = 10 for index, caractere in datac: texte += dictionnaire[index] + caractere tailledict += 1 if tailledict < taille_max: dictionnaire[tailledict] = dictionnaire[index] + caractere print(dictionnaire) return texte ````

Questions⚓︎

  • Complète le script pour trouver Ă  partir de quelle taille de texte la compression occupe moins d'espace que le texte initial. A la louche, on nĂ©glige la taille du dictionnaire (c'est le cas pour un texte très long) et on considère que chaque Ă©lĂ©ment de la compression occupe le double d'espace d'un caractère.

    Pour cela on peut utiliser le texte suivant issu du H2G2, The Hitchhiker's Guide to the Galaxy:

    Text Only
    1
    2
    ```python
    texte = '''Far out in the uncharted backwaters of the unfashionable end of the Western Spiral arm of the Galaxy lies a small unregarded yellow sun.
    

    Orbiting this at a distance of roughly ninety-eight million miles is an utterly insignificant little blue-green planet whose ape-descended life forms are so amazingly primitive that they still think digital watches are a pretty neat idea. This planet has—or rather had—a problem, which was this: most of the people living on it were unhappy for pretty much of the time. Many solutions were suggested for this problem, but most of these were largely concerned with the movements of small green pieces of paper, which is odd because on the whole it wasn’t the small green pieces of paper that were unhappy''' ```

    Et

    extrait = texte[:100] pour obtenir un texte de taille 100

  • est-ce que, dans cet exemple, Ă  partir de la première valeur oĂą la compression devient "rentable", toutes les tailles de texte supĂ©rieures sont "rentables" ?