| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- CONST
- bufSize = 32768;
- Type
- PTree = ^TTree;
- TTree = record
- info : byte;
- ti : longint;
- Left : PTree;
- Right: PTree;
- end;
- ps = ^el;
- el = record
- data : PTree;
- prev : ps;
- end;
- CONST
- fname : string[13] = 'input.txt';
- fout : string[13] = 'input.huf';
- VAR
- INP,OUT : FILE;
- USED : set of byte;
- Nums : ps;
- THead : PTree;
- {-----}
- Code : longint;
- CodeLen : byte;
- {-----}
- GO,GNum : byte;
- done : boolean;
- Size,Csize : longint;
- {---------------------------------}
- var
- {FReadBuf}
- RBBuf, RBread : ^BYTE;
- RBcount : word;
- RBsize : word;
- RBFirst, RBLast : boolean;
- {FReadBuf}
- Function FReadBuf(var F:FILE;var val:byte):boolean;
- begin
- if RBFirst then
- begin
- RBfirst:=false;
- GetMem(RBBuf,BUFSize);
- RBcount:=0;
- RBSize:=0;
- end;
- if RBLast then
- begin
- RBLast:=false;
- FreeMem(RBBuf,BufSize);
- RBFirst:=true;
- exit;
- end;
- If RBcount=RBsize then
- begin
- BlockRead(F,RBBuf^,BufSize,RBsize);
- if Rbsize=0 then
- begin
- FReadBuf:=false;
- exit;
- end;
- RBcount:=0;
- end;
- RBread:=PTR(SeG(RBBUF^),Ofs(RBbuf^)+RBcount);
- inc(RBcount);
- val:=RBread^;
- FReadBuf:=true;
- end; {FReadBuf}
- {-----------------------------------------}
- var
- {FWriteBuf}
- WBBuf,WBwrt : ^BYTE;
- WBcount : word;
- WBFirst, WBLast : boolean;
- {FWritebuf}
- Procedure FWriteBuf(var F:FILE;val:byte);
- begin
- if WBFirst then
- begin
- WBfirst:=false;
- GetMem(WBBuf,BUFSize);
- WBcount:=0;
- end;
- if WBLast then
- begin
- WBLast:=false;
- BlockWrite(F,WBBuf^,WBcount);
- FreeMem(WBBuf,BufSize);
- WBFirst:=true;
- exit;
- end;
- WBwrt:=PTR(SeG(WBBUF^),Ofs(WBbuf^)+WBcount);
- inc(WBcount);
- WBwrt^:=val;
- If WBcount=BUFsize then
- begin
- BlockWrite(F,WBBuf^,WBcount);
- WBcount:=0;
- end;
- end;{FWriteBuf}
- {-----------------------------------------}
- Procedure DelBranch(br:PTree);
- begin
- if br^.left <> nil then DelBranch(br^.left);
- if br^.right <> nil then DelBranch(br^.right);
- Dispose(br);
- end;{DelBranch}
- {------------------------------------------}
- Procedure AddItem(var HEAD:ps; VAL : PTree);
- var
- c,NEWs : ps;
- Begin
- c := HEAD;
- New(News);
- News^.data := VAL;
- News^.prev := nil;
- if c=nil then begin HEAD := NEWs; exit end;
- if val^.ti <= C^.DATA^.ti then begin News^.prev:=C; HEAD:=News; exit end;
- while (c^.prev <> nil) and
- (not ((val^.ti>C^.data^.ti) and (val^.ti<=C^.prev^.data^.ti))) do
- c:=c^.prev;
- News^.prev := c^.prev;
- C^.prev := News;
- end;{AddItem}
- {---------------------------------}
- Procedure RemoveItem(var HEAD:ps; VAL : PTree);
- var
- c,cur : ps;
- Begin
- c := HEAD;
- if c=nil then exit;
- if c^.data = val then begin HEAD:=C^.prev; Dispose(C); exit end;
- while (c^.prev <> nil) and (C^.prev^.data <> val) do c:=c^.prev;
- if c^.prev^.data <> val then exit;
- cur := c^.prev;
- C^.prev := cur^.prev;
- Dispose(cur);
- end;{RemoveItem}
- {---------------------------------}
- Procedure DeleteAll(var HEAD:ps);
- var
- c:ps;
- begin
- while HEAD <> nil do
- begin
- c:=HEAD^.prev;
- Dispose(HEAD);
- HEAD := C;
- end;
- end;{DeleteAll}
- {---------------------------------}
- Procedure GetCode(VAL:Byte;BRA:PTree;cur:longint;len:byte);
- begin
- if (Bra^.left=nil) and (Bra^.right=nil) and (BRA^.info = VAL) then
- begin
- Code := cur;
- CodeLen:=len;
- end;
- if (Bra^.left<>nil) then begin
- GetCode(val,Bra^.left,(cur shl 1) + 1,len+1);
- GetCode(val,Bra^.right,(cur shl 1),len+1)
- end;
- end;{GetCode}
- {---------------------------------}
- Function GetByte(cur:string):byte;
- var ret:byte;
- begin
- ret:=0;
- while length(cur)>0 do
- begin
- ret:=ret shl 1 + ord(cur[1])-ord('0');
- delete(cur,1,1);
- end;
- GetByte:=ret;
- end;{GetByte}
- {---------------------------------}
- Procedure IfNeedWrite(var gg:longint;var F:FILE);
- var
- FFF : byte;
- begin
- FFF := gg and $0FF;
- FWriteBuf(F,Fff);
- end;{IfNeedWrite}
- {---------------------------------}
- Function GetBit(var F:File):boolean;
- begin
- if GNum = 0 then
- begin
- GNum:=8;
- inc(CSize);
- done:=FReadBuf(F,GO);
- if not done then
- begin
- RBLast:=true;
- FReadBuf(F,GO);
- WBLast:=true;
- FWriteBuf(OUT,0);
- close(INP);
- Close(OUT);
- Halt(0);
- end;
- if csize=Size-1 then done:=FReadBuf(F,GNum);
- end;
- Dec(GNum);
- GetBit := (GO and 128) = 128;
- Go := GO shl 1;
- end;{GetBit}
- {---------------------------------}
- VAR
- CURCODE : longint;
- curlen : byte;
- CUR : byte;
- i : byte;
- Ctr : Ptree;
- BEGIN
- if (ParamCount<1) then
- begin
- WriteLn('Usage: HUF.exe <FILENAME.EXT> [OUTNAME.ext]');
- Halt(10);
- end;
- Fname := ParamStr(1);
- for size := 1 to Length(Fname) do
- fname[size] := UpCase(fname[size]);
- if pos('.HUF',fname) = 0 then
- begin
- if Paramcount = 2 then fout := ParamStr(2) else
- fout := Copy(Fname,1,pos('.',Fname)) + 'HUF';
- Assign(INP,Fname);
- Reset(INP,1);
- Size:=FileSize(INP);
- Assign(OUT,Fout);
- Rewrite(OUT,1);
- BlockWrite(OUT,Fname,14);
- curcode:=0;
- curlen:=0;
- csize:=0;
- RBFirst:=true;
- RBLast:=false;
- WBFirst:=true;
- WBLast:=false;
- while FReadBuf(INP,CUR) do
- begin
- inc(csize);
- if cur in USED then
- begin
- AddItem(HEAD)
- end
- else
- begin
- end;
- Write(#13'Complete: ',round((csize/size)*100),'%');
- end;
- if (curlen <> 0) then
- begin
- curcode := curcode shl (7-curlen);
- ifNeedWrite(curcode,OUT);
- end
- else
- curlen:=7;
- FWriteBuf(OUT,curlen);
- RBLast:=true;
- FReadBuf(INP,cur);
- WBLast:=true;
- FWriteBuf(OUT,0);
- Close(OUT);
- Close(INP);
- end
- else
- begin
- end;
- END.
|