251 lines
4.4 KiB
Plaintext
251 lines
4.4 KiB
Plaintext
program decodage;
|
|
|
|
uses crt,dos,math;
|
|
|
|
type
|
|
liste=^cellule;
|
|
cellule=record
|
|
octet:byte;
|
|
freq:longword;
|
|
suiv:liste;
|
|
gauche:liste;
|
|
droite:liste;
|
|
end;
|
|
fichier=array of byte;
|
|
catalogue=array[0..255] of byte;
|
|
|
|
var p:fichier;l:liste;premier:byte;taille,index:longword;chemin:string;
|
|
|
|
function prefixe(ind:fichier):longword;
|
|
var s,i:longword;
|
|
begin
|
|
s:=0;
|
|
for i:=length(ind)-1 downto 0 do s:=(ind[i] div 2)*trunc(power(2,7*(length(ind)-1-i)))+s;
|
|
prefixe:=s;
|
|
end;
|
|
|
|
procedure importer(var p:fichier; var l:liste; var premier:byte;var chemin:string);
|
|
var f:file;i:longword;j,longueur:byte;ind:fichier;l1,l2:liste;
|
|
begin
|
|
write('Chemin du fichier : ');
|
|
readln(chemin);
|
|
assign(f,chemin);
|
|
reset(f,1);
|
|
writeln('Importation...');
|
|
blockread(f,longueur,1);
|
|
(*Pour éviter les problèmes avec longueur=0, on fera une boucle de 0 à longueur-1*)
|
|
longueur:=longueur-1;
|
|
new(l);
|
|
l^.suiv:=nil;
|
|
setlength(ind,0);
|
|
for j:=0 to longueur do
|
|
begin
|
|
l^.gauche:=nil;
|
|
l^.droite:=nil;
|
|
blockread(f,l^.octet,1);
|
|
repeat
|
|
begin
|
|
setlength(ind,length(ind)+1);
|
|
blockread(f,ind[length(ind)-1],1);
|
|
end;
|
|
until ind[length(ind)-1] mod 2 = 0;
|
|
l^.freq:=prefixe(ind);
|
|
setlength(ind,0);
|
|
new(l1);
|
|
l1^.suiv:=l;
|
|
l:=l1;
|
|
end;
|
|
l2:=l;
|
|
l:=l^.suiv;
|
|
dispose(l2);
|
|
blockread(f,premier,1);
|
|
i:=0;
|
|
setlength(p,filesize(f)-filepos(f));
|
|
while not eof(f) do
|
|
begin
|
|
blockread(f,p[i],1);
|
|
i:=i+1;
|
|
end;
|
|
close(f);
|
|
end;
|
|
|
|
function inserer(var l:liste; var l1:liste):liste;
|
|
begin
|
|
if l=nil then
|
|
begin
|
|
l1^.suiv:=nil;
|
|
inserer:=l1;
|
|
end
|
|
else
|
|
begin
|
|
if l1^.freq<=l^.freq then
|
|
begin
|
|
l1^.suiv:=l;
|
|
inserer:=l1;
|
|
end
|
|
else
|
|
begin
|
|
l^.suiv:=inserer(l^.suiv,l1);
|
|
inserer:=l;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure arbre(var l:liste);
|
|
var l1:liste;
|
|
begin
|
|
if l^.suiv<>nil then
|
|
begin
|
|
new(l1);
|
|
l1^.gauche:=l;
|
|
l1^.droite:=l^.suiv;
|
|
l1^.freq:=l^.freq+l^.suiv^.freq;
|
|
l:=inserer(l^.suiv^.suiv,l1);
|
|
arbre(l);
|
|
end;
|
|
end;
|
|
|
|
function bit(b,position:byte):byte;
|
|
begin
|
|
bit:=(b div trunc(power(2,position)))-(2*(b div trunc(power(2,position+1))));
|
|
end;
|
|
|
|
procedure interpreter(l:liste;var p:fichier;premier:byte);
|
|
var m:byte;l1:liste;f:fichier;i:longword;
|
|
begin
|
|
m:=premier;
|
|
l1:=l;
|
|
setlength(f,0);
|
|
for i:=0 to length(p)-1 do
|
|
begin
|
|
repeat
|
|
begin
|
|
if bit(p[i],m)=0 then l1:=l1^.gauche else l1:=l1^.droite;
|
|
if ((l1^.gauche=nil) and (l1^.droite=nil)) then
|
|
begin
|
|
setlength(f,length(f)+1);
|
|
f[length(f)-1]:=l1^.octet;
|
|
l1:=l;
|
|
end;
|
|
m:=m-1;
|
|
end;
|
|
until m=255;
|
|
m:=7;
|
|
end;
|
|
p:=f;
|
|
setlength(f,0);
|
|
end;
|
|
|
|
procedure coder(p:fichier;taille:longword);
|
|
var ref,car:catalogue;i:longword;j,k,l:byte;f:fichier;
|
|
begin
|
|
for i:=0 to 255 do ref[i]:=i;
|
|
car:=ref;
|
|
setlength(f,taille);
|
|
for i:=0 to taille-1 do
|
|
begin
|
|
j:=p[i];
|
|
f[i]:=car[j];
|
|
l:=car[j];
|
|
for k:=j downto 1 do
|
|
begin
|
|
car[k]:=car[k-1];
|
|
end;
|
|
car[0]:=l;
|
|
end;
|
|
p:=f;
|
|
setlength(f,0);
|
|
end;
|
|
|
|
function prefixe(ind:fichier;taille:longword):longword;
|
|
var s,i:longword;
|
|
begin
|
|
s:=0;
|
|
for i:=taille-1 downto 0 do s:=(ind[i] div 2)*trunc(power(2,7*(taille-1-i)))+s;
|
|
prefixe:=s;
|
|
end;
|
|
|
|
procedure preliminaire(var f:fichier;var index:longword);
|
|
var ind,p:fichier;i,j:longword;
|
|
begin
|
|
i:=0;
|
|
setlength(ind,0);
|
|
repeat
|
|
begin
|
|
setlength(ind,i+1);
|
|
ind[i]:=f[i];
|
|
i:=i+1;
|
|
end;
|
|
until ind[i-1] mod 2 = 0;
|
|
index:=prefixe(ind,i);
|
|
setlength(ind,0);
|
|
setlength(p,length(f)-i);
|
|
for j:=i to length(f)-1 do p[j-i]:=f[i];
|
|
f:=p;
|
|
setlength(p,0);
|
|
end;
|
|
|
|
function decode(index,taille:longword;t:fichier):fichier;
|
|
var i,j,sum:longword;C,P:array of longword;S:fichier;
|
|
begin
|
|
setlength(C,256);
|
|
setlength(P,taille);
|
|
setlength(S,taille);
|
|
for i:=0 to 255 do C[i]:=0;
|
|
for i:=0 to taille-1 do
|
|
begin
|
|
P[i]:=C[t[i]];
|
|
C[t[i]]:=C[t[i]]+1;
|
|
end;
|
|
sum:=0;
|
|
for i:=0 to 255 do
|
|
begin
|
|
sum:=sum+C[i];
|
|
C[i]:=sum-C[i];
|
|
end;
|
|
i:=index;
|
|
for j:=taille-1 downto 0 do
|
|
begin
|
|
S[j]:=t[i];
|
|
i:=P[i]+C[t[i]];
|
|
end;
|
|
decode:=S;
|
|
end;
|
|
|
|
function nouv_chemin(chemin,nom: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+'/'+nom
|
|
end;
|
|
|
|
procedure ecrire(d:fichier;taille:longword;chemin:string);
|
|
var f1:file;nom:string;i:longword;
|
|
begin
|
|
write('Nom du fichier : ');
|
|
readln(nom);
|
|
assign(f1,nouv_chemin(chemin,nom));
|
|
rewrite(f1,1);
|
|
writeln('Écriture de la séquence...');
|
|
for i:=0 to taille-1 do
|
|
begin
|
|
blockwrite(f1,d[i],1);
|
|
end;
|
|
close(f1);
|
|
end;
|
|
|
|
begin
|
|
importer(p,l,premier,chemin);
|
|
arbre(l);
|
|
interpreter(l,p,premier);
|
|
taille:=length(p);
|
|
coder(p,taille);
|
|
preliminaire(p,index);
|
|
taille:=length(p);
|
|
p:=decode(index,taille,p);
|
|
writeln('ok');
|
|
ecrire(p,taille,chemin);
|
|
end. |