program codage; uses crt,dos,math; type anagramme=^cellule1; cellule1=record octet:byte; prec:anagramme; suiv:anagramme; end; decalage=array of anagramme; catalogue=array[0..255] of byte; fichier=array of byte; bit=0..1; liste=^cellule2; cellule2=record octet:byte; freq:longword; suiv:liste; gauche:liste; droite:liste; end; tableau=array[0..255] of liste; sauvegarde=array of liste; final=array[0..255] of array of bit; var f:fichier;a:anagramme;d:decalage;taille,p:longword;l:liste;fin:final;longueur:byte;s:sauvegarde;chemin:string; procedure importer(var p:anagramme; var taille:longword; var chemin:string); var f:file;p1:anagramme; begin write('Chemin du fichier : '); readln(chemin); if chemin[length(chemin)]=' ' then delete(chemin,length(chemin),1); assign(f,chemin); reset(f,1); new(p); p1:=p; writeln('Importation...'); while not eof(f) do begin new(p1^.suiv); p1^.suiv^.prec:=p1; p1:=p1^.suiv; blockread(f,p1^.octet,1); end; taille:=filesize(f); close(f); p:=p^.suiv; p1^.suiv:=p; p^.prec:=p1; end; function EstSuperieur(p1,p2:anagramme;longueur:longword):boolean; var pa,pb:anagramme;i:longword; begin i:=1; pa:=p1; pb:=p2; while ((i<=longueur) and (pa^.octet=pb^.octet)) do begin pa:=pa^.suiv; pb:=pb^.suiv; i:=i+1; end; if pa^.octet>pb^.octet then EstSuperieur:=true else EstSuperieur:=false; end; function inserer(p:anagramme;t:decalage;debut,fin,taille:longword):longword; var milieu:longword; begin if fin-debut=0 then inserer:=debut else begin milieu:=(debut+fin) div 2; if EstSuperieur(t[milieu],p,taille) then inserer:=inserer(p,t,debut,milieu,taille) else inserer:=inserer(p,t,milieu+1,fin,taille); end; end; procedure reindex(var t:decalage;p:anagramme;i,taille:longword; var position:longword); var j,k:longword; begin j:=inserer(p,t,0,i,taille); setlength(t,i+1); if j<=position then position:=position+1; for k:=i downto j do t[k+1]:=t[k]; t[j]:=p; end; procedure tabler(var t:decalage; var p:anagramme;taille:longword; var position:longword); var i:longword;x:byte; begin x:=1; setlength(t,1); t[0]:=p; position:=0; for i:=1 to taille-1 do begin p:=p^.suiv; reindex(t,p,i,taille,position); if ((i+1)*100) div taille >= x then begin writeln(x,'% des décalages indexés'); x:=x+1; end; end; end; procedure prefixe(n:longword; var p:anagramme; var i:integer); var p1:anagramme; begin i:=0; new(p); p1:=p; repeat begin i:=i+1; new(p1^.suiv); p1^.suiv^.prec:=p1; p1:=p1^.suiv; p1^.octet:=((n-(trunc(power(2,7*i))*(n div trunc(power(2,7*i))))) div trunc(power(2,7*(i-1))))*2+1; end; until n div trunc(power(2,7*i))=0; p:=p^.suiv; p1^.suiv:=p; p^.prec:=p1; p^.octet:=p^.octet-1; p:=p^.prec; end; procedure dernier(var d:decalage); var i:longword; begin for i:=0 to length(d)-1 do d[i]:=d[i]^.prec; end; procedure transformer(n:longword;d:decalage;taille:longword;var f:fichier); var i:longword;j:integer;p:anagramme; begin setlength(f,0); prefixe(n,p,j); writeln('Position du motif original fixée à ',n,', codée sur ',j,' octet(s)'); (*Écriture du préfixe...*) setlength(f,j+taille); for i:=0 to j-1 do begin f[i]:=p^.octet; p:=p^.prec; end; writeln('Écriture de la séquence codée...'); dernier(d); for i:=0 to taille-1 do begin f[i+j]:=d[i]^.octet; dispose(d[i]); end; setlength(d,0); end; procedure coder(var p:fichier;taille:longword); var ref,car:catalogue;i:longword;j,k,l:byte;f:fichier; begin setlength(f,taille); for i:=0 to 255 do ref[i]:=i; car:=ref; for i:=0 to taille-1 do begin j:=p[i]; f[i]:=ref[j]; l:=car[ref[j]]; for k:=ref[j] downto 1 do begin car[k]:=car[k-1]; ref[car[k]]:=k; end; car[0]:=l; ref[l]:=0; end; p:=f; setlength(f,0); end; procedure trier(var l:liste); var l1,l2:liste; begin l1:=l; if l<>nil then begin while l1^.suiv<>nil do begin if l1^.suiv^.freqnil then begin new(l1); l1^.gauche:=l; l1^.droite:=l^.suiv; l1^.freq:=l^.freq+l^.suiv^.freq; branche(l1^.gauche,0,fin); branche(l1^.droite,1,fin); l:=inserer2(l^.suiv^.suiv,l1); arbre(l,fin); end; end; procedure nombrelong(n:longword; var nombre:fichier); var i:longword; begin i:=1; setlength(nombre,0); repeat begin setlength(nombre,i); nombre[i-1]:=((n-(trunc(power(2,7*i))*(n div trunc(power(2,7*i))))) div trunc(power(2,7*(i-1))))*2+1; i:=i+1; end; until n div trunc(power(2,7*(i-1)))=0; nombre[0]:=nombre[0]-1; end; function nouv_chemin(chemin:string):string; var i:byte;s:string; begin s:=chemin; i:=length(chemin); while s[i]<>'.' do i:=i-1; delete(s,i,length(chemin)-i+1); nouv_chemin:=s+'.cmp' end; procedure ecrire(fin:final;p:fichier;taille:longword;s:sauvegarde;longueur:byte;chemin:string); var f:file;i,m:longword;j,k:byte;nombre:fichier; begin assign(f,nouv_chemin(chemin)); rewrite(f,1); writeln('Écriture du dictionnaire...'); blockwrite(f,longueur,1); for i:=high(s) downto 0 do begin blockwrite(f,s[i]^.octet,1); nombrelong(s[i]^.freq,nombre); for j:=length(nombre)-1 downto 0 do blockwrite(f,nombre[j],1); end; writeln('Recherche du point de départ des données...'); k:=0; m:=0; for i:=0 to high(s) do m:=length(fin[s[i]^.octet])*s[i]^.freq+m; m:=(m-1) mod 8; blockwrite(f,m,1); writeln('Écriture des données...'); j:=0; for i:=0 to taille-1 do begin for j:=high(fin[p[i]]) downto 0 do begin k:=(fin[p[i]][j])*trunc(power(2,m))+k; if m=0 then begin blockwrite(f,k,1); k:=0; m:=7; end else m:=m-1; end; end; end; procedure compter(p:fichier;taille:longword; var l:liste; var longueur:byte); var i:longword;j:byte;l1:liste;t:tableau; begin writeln('Bilan des octets...'); j:=255; longueur:=0; for i:=0 to 255 do t[i]:=nil; for i:=0 to taille-1 do begin if t[p[i]]=nil then begin longueur:=longueur+1; new(t[p[i]]); t[p[i]]^.freq:=0; t[p[i]]^.octet:=p[i]; t[p[i]]^.gauche:=nil; t[p[i]]^.droite:=nil; t[p[i]]^.suiv:=nil; if p[i]0 then begin write(i,' '); for j:=high(fin[i]) downto 0 do write(fin[i][j]); writeln; end; end; end; procedure verification2(l:liste); begin if l<>nil then begin writeln(l^.octet,': ',l^.freq); verification2(l^.suiv); end; end; function sauver(l:liste):sauvegarde; var s:sauvegarde; begin setlength(s,0); while l<>nil do begin setlength(s,length(s)+1); s[length(s)-1]:=l; l:=l^.suiv; end; sauver:=s; end; begin writeln('Algorithme de Burrows-Weeler :'); importer(a,taille,chemin); writeln('Création des décalages...'); tabler(d,a,taille,p); transformer(p,d,taille,f); writeln('Algorithme de Move-To-Front...'); taille:=length(f); coder(f,taille); writeln('Algorithme de Huffman :'); compter(f,taille,l,longueur); writeln('Tri préliminaire...'); trier(l); s:=sauver(l); writeln('Création de l''arbre-dictionnaire...'); arbre(l,fin); ecrire(fin,f,taille,s,longueur,chemin); end.