{$A+,B-,D+,E+,F-,G-,I+,L+,N-,O-,P-,Q+,R+,S+,T-,V+,X+,Y+}
{$M 16384,0,655360}
{
1) u‘koduoja tarpus;
2) u‘koduoja standartinius Turbo Pascalio ‘od‘ius;
3) u‘koduoja visus besikartojancius ‘od‘ius;
}
program simple_RLE_plus_base_pascal_words_plus_all_repeating_words;
  uses hash;
  const maxbuf = 65000;
        tarpas = 32;
        enter = 13;
        kablelis = 44;
        raides = ['0'..'9', 'A'..'Z', 'a'..'z', '_'];
  type buffer = array [1..maxbuf] of byte;
       ilgiai = array [0..maxbuf div 2] of byte;
  var buf : ^buffer;
      il : ilgiai;
      sar : hash_lentele;
  procedure arch (s1, s2 : string);
    var fin, fout : file;
        saug,       { saugo dar neira˛yt… ¨ byl… informacij… }
        isn : byte; { rodo, kiek bit— i˛ saugojimo bait— yra u‘imta}
        kelintas, laipsnis : word;
        i, bitais : byte;
        dabar, dydis : word;
        nekoduota : boolean;
        tmp : string;
    procedure issaugok (var saug, isn : byte);
    begin
      blockwrite (fout, saug, 1);
      saug := 0;
      isn := 0;
    end;
    procedure padek_bitu (s : string);
      var i : byte;
    begin
      for i := 1 to length (s) do
        begin
          saug := saug shl 1 + (ord (s[i]) - 48);
          inc (isn);
          if isn = 8
            then
              begin
                blockwrite (fout, saug, 1);
                saug := 0;
                isn := 0;
              end;
        end;
    end;
    procedure padek_eilute (s : string);
      var i, simb : byte;
    begin
      for i := 1 to length (s) do
        begin
          simb := ord (s[i]);
          saug := saug shl (8 - isn) + simb shr isn;
          blockwrite (fout, saug, 1);
          saug := byte (simb shl (8 - isn)) shr (8 - isn);
        end;
    end;
    procedure padek_skaiciu (sk : word; bitu : byte);
    begin
      while bitu + isn >= 8 do
        begin
          saug := saug shl (8 - isn) + byte (sk shr (bitu + isn - 8));
          blockwrite (fout, saug, 1);
          sk := sk shl (24 - bitu - isn) shr (24 - bitu - isn);
          bitu := bitu + isn - 8;
          saug := 0;
          isn := 0;
        end;
      saug := saug shl bitu + sk;
      isn := isn + bitu;
    end;
    procedure koduok_tarpus (var nekoduota : boolean; var tmp : string);
      var kiek : byte;
    begin
      kiek := 0;
      inc (dabar);
      while (dabar < dydis) and (buf^[dabar] = tarpas) and (kiek < 63) do
        begin
          inc (dabar);
          inc (kiek);
        end;
      if kiek > 0
        then
          begin
            if tmp <> ''
              then
                begin
                  padek_bitu ('00');
                  padek_skaiciu (length (tmp), 7);
                  padek_eilute (tmp);
                  padek_bitu ('01');
                  dec (kiek);
                  nekoduota := false;
                  tmp := '';
                end;
            padek_bitu ('01');
            padek_skaiciu (kiek, 6);
          end
        else
          begin
            tmp := tmp + chr (tarpas);
            nekoduota := true;
          end;
    end;
    procedure atlaisvink_tempa (var nekoduota : boolean; var tmp : string);
      var gale : byte;
    begin
      gale := 0;
      case ord (tmp[length (tmp)]) of
        tarpas: gale := tarpas;
        kablelis: gale := kablelis;
      end;
      if gale > 0
        then delete (tmp, length (tmp), 1);
      padek_bitu ('00');
      padek_skaiciu (length (tmp), 7);
      padek_eilute (tmp);
      case gale of
        tarpas: padek_bitu ('01');
        kablelis: padek_bitu ('10');
        else padek_bitu ('00');
      end;
      nekoduota := false;
      tmp := '';
    end;
    procedure koduok_zodi (var nekoduota : boolean; var tmp : string);
      var zod : string;
          ilg : byte;
          nr : integer;
    begin
      zod := '';
      while chr (buf^[dabar]) in raides do
        begin
          zod := zod + chr (buf^[dabar]);
          inc (dabar);
        end;
      ilg := length (zod);
      if ilg > 1
        then
          begin
            nr := hash_numeris (ht, zod);
            if nr > 0
              then
                begin
                  if tmp <> ''
                    then atlaisvink_tempa (nekoduota, tmp);
                  padek_bitu ('10');
                  padek_skaiciu (nr, 8);
                  case buf^[dabar] of
                    tarpas: begin
                              padek_bitu ('01');
                              inc (dabar);
                            end;
                    kablelis: begin
                                padek_bitu ('10');
                                inc (dabar);
                              end;
                    enter: begin
                             padek_bitu ('11');
                             inc (dabar, 2);
                           end;
                    else padek_bitu ('00');
                  end;
                end
              else
                begin
                  nr := hash_numeris (sar, zod);
                  if nr > 0
                    then
                      begin
                        if tmp <> ''
                          then atlaisvink_tempa (nekoduota, tmp);
                        padek_bitu ('11');
                        padek_skaiciu (nr, bitais);
                        case buf^[dabar] of
                          tarpas: begin
                                    padek_bitu ('01');
                                    inc (dabar);
                                  end;
                          kablelis: begin
                                      padek_bitu ('10');
                                      inc (dabar);
                                    end;
                          enter: begin
                                   padek_bitu ('11');
                                   inc (dabar, 2);
                                 end;
                          else padek_bitu ('00');
                        end;
                      end
                    else
                      begin
                        tmp := tmp + zod;
                        hash_pridek (sar, zod, kelintas);
                        inc (kelintas);
                        if kelintas = laipsnis
                          then
                            begin
                              laipsnis := laipsnis * 2;
                              inc (bitais);
                            end;
                        nekoduota := true;
                      end;
                end;
          end
        else
          begin
            tmp := tmp + zod;
            nekoduota := true;
          end;
    end;
    procedure koduok_nekoduota;
      var s : string;
    begin
      s := '';
      while (dabar <= dydis) and (buf^[dabar] <> enter) do
        begin
          s := s + chr (buf^[dabar]);
          inc (dabar);
          if (dabar + 2 < dydis) and (buf^[dabar] = tarpas) and
             (buf^[dabar + 1] = tarpas) and (buf^[dabar + 2] = tarpas)
            then break;
        end;
      padek_bitu ('00');
      padek_skaiciu (length (s), 7);
      padek_eilute (s);
      case buf^[dabar] of
        enter: begin
                 padek_bitu ('11');
                 inc (dabar, 2);
               end;
        tarpas: begin
                  padek_bitu ('01');
                  inc (dabar);
                end;
        else padek_bitu ('00');
      end;
    end;
  begin
    assign (fin, s1);
    reset (fin, 1);
    blockread (fin, buf^, maxbuf, dydis);
    close (fin);
    assign (fout, s2);
    rewrite (fout, 1);
    blockwrite (fout, dydis, sizeof (dydis));
    saug := 0;
    isn := 0;
    kelintas := 0;
    bitais := 1;
    laipsnis := 2;
    dabar := 1;
    while dabar <= dydis do
      begin
        nekoduota := true;
        tmp := '';{ }
        while (dabar <= dydis) and nekoduota do
          begin
            while buf^[dabar] = tarpas do
              koduok_tarpus (nekoduota, tmp);
            koduok_zodi (nekoduota, tmp);
            while (dabar <= dydis) and not (chr (buf^[dabar]) in raides) and
                  (buf^[dabar] <> enter) and (buf^[dabar] <> tarpas) do
              begin
                tmp := tmp + chr (buf^[dabar]);
                inc (dabar);
                nekoduota := true;
              end;
            if buf^[dabar] = enter
              then
                begin
                  padek_bitu ('00');
                  padek_skaiciu (length (tmp), 7);
                  padek_eilute (tmp);
                  padek_bitu ('11');
                  nekoduota := false;
                  tmp := '';
                  inc (dabar, 2);
                end;
          end;
      end;
    if nekoduota and (tmp <> '')
      then
        begin
          padek_bitu ('00');
          padek_skaiciu (length (tmp), 7);
          padek_eilute (tmp);
          padek_bitu ('00');
        end;
    if isn > 0
      then
        begin
          saug := saug shl (8 - isn);
          blockwrite (fout, saug, 1);
        end;
    close (fout);
  end;
  procedure dearch (s1, s2 : string);
    var fin, fout : file;
        dabar, dydis, kiek, jau : word;
        s, inf, tmp, zod : string;
        i, ilg, sk : byte;
        kelintas, laipsnis : word;
        nr : integer;
        bitais : byte;
        tmp_sar : sarasas;
    procedure paimk_bitu (var s : string; kiek : byte);
      var i, baitas : byte;
          tmp : string;
    begin
      while kiek > length (inf) do
        begin
          baitas := buf^[dabar];
          inc (dabar);
          tmp := '';
          for i := 1 to 8 do
            begin
              tmp := chr (baitas and 1) + tmp;
              baitas := baitas shr 1;
            end;
          inf := inf + tmp;
        end;
      s := copy (inf, 1, kiek);
      delete (inf, 1, kiek);
    end;
    function skaicius (var s : string) : word;
      var i : byte;
          sk : word;
    begin
      sk := 0;
      for i := 1 to length (s) do
        sk := sk shl 1 + ord (s[i]);
      skaicius := sk;
    end;
  begin
    assign (fin, s1);
    reset (fin, 1);
    blockread (fin, dydis, sizeof (dydis));
    blockread (fin, buf^, maxbuf, kiek);
    close (fin);
    assign (fout, s2);
    rewrite (fout, 1);
    inf := '';
    dabar := 1;
    jau := 0;
    kelintas := 0;
    bitais := 1;
    laipsnis := 2;
    while jau < dydis do
      begin
        paimk_bitu (s, 2);
        case skaicius (s) of
          0: begin
               paimk_bitu (s, 7);
               ilg := skaicius (s);
               tmp := '';
               for i := 1 to ilg do
                 begin
                   paimk_bitu (s, 8);
                   tmp := tmp + chr (skaicius (s));
                 end;
               blockwrite (fout, tmp[1], ilg);
               while tmp <> '' do
                 begin
                   while (tmp <> '') and not (tmp[1] in raides) do
                     delete (tmp, 1, 1);
                   zod := '';
                   while (tmp <> '') and (tmp[1] in raides) do
                     begin
                       zod := zod + tmp[1];
                       delete (tmp, 1, 1);
                     end;
                   if length (zod) > 1
                     then
                       begin
                         hash_pridek (sar, zod, kelintas);
                         il[kelintas] := length (zod);
                         inc (kelintas);
                         if kelintas = laipsnis
                           then
                             begin
                               laipsnis := laipsnis * 2;
                               inc (bitais);
                             end;
                       end;
                 end;
               paimk_bitu (s, 2);
               case skaicius (s) of
                 0: tmp := '';
                 1: tmp := ' ';
                 2: tmp := ',';
                 3: tmp := #13#10;
               end;
               blockwrite (fout, tmp[1], length (tmp));
               inc (jau, ilg);
               inc (jau, length (tmp));
             end;
          1: begin
               paimk_bitu (s, 6);
               sk := skaicius (s) + 1;
               tmp := '';
               for i := 1 to sk do
                 tmp := tmp + chr (tarpas);
               blockwrite (fout, tmp[1], sk);
               inc (jau, sk);
             end;
          2: begin
               paimk_bitu (s, 8);
               tmp := pagr[skaicius (s)];
               paimk_bitu (s, 2);
               case skaicius (s) of
                 1: tmp := tmp + chr (tarpas);
                 2: tmp := tmp + chr (kablelis);
                 3: tmp := tmp + #13#10;
               end;
               ilg := length (tmp);
               blockwrite (fout, tmp[1], ilg);
               inc (jau, ilg);
             end;
          3: begin
               paimk_bitu (s, bitais);
               nr := skaicius (s);
               ilg := il[nr];
               tmp_sar := sar[ilg];
               while tmp_sar^.nr <> nr do
                 tmp_sar := tmp_sar^.kitas;
               tmp := tmp_sar^.st;
               paimk_bitu (s, 2);
               case skaicius (s) of
                 1: tmp := tmp + chr (tarpas);
                 2: tmp := tmp + chr (kablelis);
                 3: tmp := tmp + #13#10;
               end;
               blockwrite (fout, tmp[1], length (tmp));
               inc (jau, length (tmp));
             end;
        end;
      end;
    close (fout);
  end;
begin
  new (buf);
  fillchar (buf^, sizeof (buf^), 0);
  hash_paruosk (ht);
  hash_paruosk (sar);
  hash_pagr (ht);
  write ('Encoding...');
  arch ('arch.txt', 'arch.e03');
  writeln (' done');
  hash_isvalyk (sar);
  hash_paruosk (sar);
  write ('Decoding...');
  dearch ('arch.e03', 'arch.d03');
  writeln (' done');
  hash_isvalyk (sar);
  hash_isvalyk (ht);
  dispose (buf);
end.{$A+,B-,D+,E+,F-,G-,I+,L+,N-,O-,P-,Q+,R+,S+,T-,V+,X+,Y+}
{$M 16384,0,655360}
{
1) u‘koduoja tarpus;
2) u‘koduoja standartinius Turbo Pascalio ‘od‘ius;
3) u‘koduoja visus besikartojan‡ius ‘od‘ius;
4) u‘koduoja visus besikartojan‡ius simboli— kratinius, esan‡ius tarp ‘od‘i—;
}
program simple_RLE_plus_base_pascal_words_plus_all_repeating_words_plus_all_repeating_nonwords;
  const maxbuf = 65000;
        tarpas = 32;
        enter = 13;
        kablelis = 44;
        raides = ['0'..'9', 'A'..'Z', 'a'..'z', '_'];
  type buffer = array [1..maxbuf] of byte;
       ilgiai = array [0..maxbuf div 2] of byte;
  {$I zodziai.inc}
  var buf : ^buffer;
      il : ilgiai;
      sar : hash_lentele;
  procedure arch (s1, s2 : string);
    var fin, fout : file;
        saug,       { saugo dar ne¨ra˛yt… ¨ byl… informacij… }
        isn : byte; { rodo, kiek bit— i˛ saugojimo bait— yra u‘imta}
        kelintas, laipsnis : word;
        nr : integer;
        i, bitais : byte;
        dabar, dydis : word;
        nekoduota : boolean;
        tmp, nezod : string;
    procedure issaugok (var saug, isn : byte);
    begin
      blockwrite (fout, saug, 1);
      saug := 0;
      isn := 0;
    end;
    procedure padek_bitu (s : string);
      var i : byte;
    begin
      for i := 1 to length (s) do
        begin
          saug := saug shl 1 + (ord (s[i]) - 48);
          inc (isn);
          if isn = 8
            then
              begin
                blockwrite (fout, saug, 1);
                saug := 0;
                isn := 0;
              end;
        end;
    end;
    procedure padek_eilute (s : string);
      var i, simb : byte;
    begin
      for i := 1 to length (s) do
        begin
          simb := ord (s[i]);
          saug := saug shl (8 - isn) + simb shr isn;
          blockwrite (fout, saug, 1);
          saug := byte (simb shl (8 - isn)) shr (8 - isn);
        end;
    end;
    procedure padek_skaiciu (sk : word; bitu : byte);
    begin
      while bitu + isn >= 8 do
        begin
          saug := saug shl (8 - isn) + byte (sk shr (bitu + isn - 8));
          blockwrite (fout, saug, 1);
          sk := sk shl (24 - bitu - isn) shr (24 - bitu - isn);
          bitu := bitu + isn - 8;
          saug := 0;
          isn := 0;
        end;
      saug := saug shl bitu + sk;
      isn := isn + bitu;
    end;
    procedure atlaisvink_tempa (var nekoduota : boolean; var tmp : string);
      var gale : byte;
    begin
{if length (tmp) = 1 then write ('I') else write ('O');
if tmp[length (tmp)] in [#10, #13] then write ('#');{}
      gale := 0;
      case ord (tmp[length (tmp)]) of
        tarpas: gale := tarpas;
        kablelis: gale := kablelis;
        enter: gale := enter;
      end;
      if gale > 0
        then delete (tmp, length (tmp), 1);
      padek_bitu ('00');
      padek_skaiciu (length (tmp), 7);
      padek_eilute (tmp);
      case gale of
        tarpas: padek_bitu ('01');
        kablelis: padek_bitu ('10');
        enter: padek_bitu ('11');
        else padek_bitu ('00');
      end;
      nekoduota := false;
      tmp := '';
    end;
    procedure koduok_tarpus (var nekoduota : boolean; var tmp : string);
      var kiek : byte;
    begin
      kiek := 0;
      inc (dabar);
      while (dabar < dydis) and (buf^[dabar] = tarpas) and (kiek < 63) do
        begin
          inc (dabar);
          inc (kiek);
        end;
      if kiek > 0
        then
          begin
            if tmp <> ''
              then
                begin
                  tmp := tmp + ' ';
                  atlaisvink_tempa (nekoduota, tmp);
                  dec (kiek);
                end;
            padek_bitu ('01');
            padek_skaiciu (kiek, 6);
          end
        else
          begin
            tmp := tmp + chr (tarpas);
            nekoduota := true;
          end;
    end;
    procedure koduok_zodi (var nekoduota : boolean; var tmp : string);
      var zod : string;
          ilg : byte;
          nr : integer;
    begin
      zod := '';
      while chr (buf^[dabar]) in raides do
        begin
          zod := zod + chr (buf^[dabar]);
          inc (dabar);
        end;
      ilg := length (zod);
      if ilg > 1
        then
          begin
            nr := hash_numeris (ht, zod);
            if nr > 0
              then
                begin
                  if tmp <> ''
                    then atlaisvink_tempa (nekoduota, tmp);
                  padek_bitu ('10');
                  padek_skaiciu (nr, 8);
                  case buf^[dabar] of
                    tarpas: begin
                              padek_bitu ('01');
                              inc (dabar);
                            end;
                    kablelis: begin
                                padek_bitu ('10');
                                inc (dabar);
                              end;
                    enter: begin
                             padek_bitu ('11');
                             inc (dabar, 2);
                           end;
                    else padek_bitu ('00');
                  end;
                end
              else
                begin
                  nr := hash_numeris (sar, zod);
                  if nr > 0
                    then
                      begin
                        if tmp <> ''
                          then atlaisvink_tempa (nekoduota, tmp);
                        padek_bitu ('11');
                        padek_skaiciu (nr, bitais);
                        case buf^[dabar] of
                          tarpas: begin
                                    padek_bitu ('01');
                                    inc (dabar);
                                  end;
                          kablelis: begin
                                      padek_bitu ('10');
                                      inc (dabar);
                                    end;
                          enter: begin
                                   padek_bitu ('11');
                                   inc (dabar, 2);
                                 end;
                          else padek_bitu ('00');
                        end;
                      end
                    else
                      begin
                        tmp := tmp + zod;
                        hash_pridek (sar, zod, kelintas);
                        inc (kelintas);
                        if kelintas = laipsnis
                          then
                            begin
                              laipsnis := laipsnis * 2;
                              inc (bitais);
                            end;
                        nekoduota := true;
                      end;
                end;
          end
        else
          begin
            tmp := tmp + zod;
            nekoduota := true;
          end;
    end;
    procedure koduok_nekoduota;
      var s : string;
    begin
      s := '';
      while (dabar <= dydis) and (buf^[dabar] <> enter) do
        begin
          s := s + chr (buf^[dabar]);
          inc (dabar);
          if (dabar + 2 < dydis) and (buf^[dabar] = tarpas) and
             (buf^[dabar + 1] = tarpas) and (buf^[dabar + 2] = tarpas)
            then break;
        end;
      padek_bitu ('00');
      padek_skaiciu (length (s), 7);
      padek_eilute (s);
      case buf^[dabar] of
        enter: begin
                 padek_bitu ('11');
                 inc (dabar, 2);
               end;
        tarpas: begin
                  padek_bitu ('01');
                  inc (dabar);
                end;
        else padek_bitu ('00');
      end;
    end;
  begin
    assign (fin, s1);
    reset (fin, 1);
    blockread (fin, buf^, maxbuf, dydis);
    close (fin);
    assign (fout, s2);
    rewrite (fout, 1);
    blockwrite (fout, dydis, sizeof (dydis));
    saug := 0;
    isn := 0;
    kelintas := 0;
    bitais := 1;
    laipsnis := 2;
    dabar := 1;
    while dabar <= dydis do
      begin
        nekoduota := true;
        tmp := '';{ }
        while (dabar <= dydis) and nekoduota do
          begin
            while buf^[dabar] = tarpas do
              koduok_tarpus (nekoduota, tmp);
            koduok_zodi (nekoduota, tmp);
            nezod := '';
            while (dabar <= dydis) and not (chr (buf^[dabar]) in raides) and
                  (buf^[dabar] <> enter) and (buf^[dabar] <> tarpas) do
              begin
                nezod := nezod + chr (buf^[dabar]);
                inc (dabar);
              end;
            if length (nezod) > 1
              then
                begin
                  nr := hash_numeris (sar, nezod);
                  if nr > 0
                    then
                      begin
                        if tmp <> ''
                          then atlaisvink_tempa (nekoduota, tmp);
                        padek_bitu ('11');
                        padek_skaiciu (nr, bitais);
                        case buf^[dabar] of
                          tarpas: begin
                                    padek_bitu ('01');
                                    inc (dabar);
                                  end;
                          kablelis: begin
                                      padek_bitu ('10');
                                      inc (dabar);
                                    end;
                          enter: begin
                                   padek_bitu ('11');
                                   inc (dabar, 2);
                                 end;
                          else padek_bitu ('00');
                        end;
                      end
                    else
                      begin
                        tmp := tmp + nezod;
                        hash_pridek (sar, nezod, kelintas);
                        inc (kelintas);
                        if kelintas = laipsnis
                          then
                            begin
                              laipsnis := laipsnis * 2;
                              inc (bitais);
                            end;
                        nekoduota := true;
                      end;
                end
              else
                begin
                  tmp := tmp + nezod;
                  nekoduota := true;
                end;
            if buf^[dabar] = enter
              then
                begin
                  tmp := tmp + #13;
                  atlaisvink_tempa (nekoduota, tmp);
                  inc (dabar, 2);
                end;
          end;
      end;
    if nekoduota and (tmp <> '')
      then
        begin
          padek_bitu ('00');
          padek_skaiciu (length (tmp), 7);
          padek_eilute (tmp);
          padek_bitu ('00');
        end;
    if isn > 0
      then
        begin
          saug := saug shl (8 - isn);
          blockwrite (fout, saug, 1);
        end;
    close (fout);
  end;
  procedure dearch (s1, s2 : string);
    var fin, fout : file;
        dabar, dydis, kiek, jau : word;
        s, inf, tmp, zod, nezod : string;
        i, ilg, sk : byte;
        kelintas, laipsnis : word;
        nr : integer;
        bitais : byte;
        tmp_sar : sarasas;
    procedure paimk_bitu (var s : string; kiek : byte);
      var i, baitas : byte;
          tmp : string;
    begin
      while kiek > length (inf) do
        begin
          baitas := buf^[dabar];
          inc (dabar);
          tmp := '';
          for i := 1 to 8 do
            begin
              tmp := chr (baitas and 1) + tmp;
              baitas := baitas shr 1;
            end;
          inf := inf + tmp;
        end;
      s := copy (inf, 1, kiek);
      delete (inf, 1, kiek);
    end;
    function skaicius (var s : string) : word;
      var i : byte;
          sk : word;
    begin
      sk := 0;
      for i := 1 to length (s) do
        sk := sk shl 1 + ord (s[i]);
      skaicius := sk;
    end;
  begin
    assign (fin, s1);
    reset (fin, 1);
    blockread (fin, dydis, sizeof (dydis));
    blockread (fin, buf^, maxbuf, kiek);
    close (fin);
    assign (fout, s2);
    rewrite (fout, 1);
    inf := '';
    dabar := 1;
    jau := 0;
    kelintas := 0;
    bitais := 1;
    laipsnis := 2;
    while jau < dydis do
      begin
        paimk_bitu (s, 2);
        case skaicius (s) of
          0: begin
               paimk_bitu (s, 7);
               ilg := skaicius (s);
               tmp := '';
               for i := 1 to ilg do
                 begin
                   paimk_bitu (s, 8);
                   tmp := tmp + chr (skaicius (s));
                 end;
               blockwrite (fout, tmp[1], ilg);
               while tmp <> '' do
                 begin
                   while (tmp <> '') and (tmp[1] = ' ') do
                     delete (tmp, 1, 1);
                   nezod := '';
                   while (tmp <> '') and not (tmp[1] in raides) and
                         (tmp[1] <> ' ') and (tmp[1] <> #13) do
                     begin
                       nezod := nezod + tmp[1];
                       delete (tmp, 1, 1);
                     end;
                   if length (nezod) > 1
                     then
                       begin
                         hash_pridek (sar, nezod, kelintas);
                         il[kelintas] := length (nezod);
                         inc (kelintas);
                         if kelintas = laipsnis
                           then
                             begin
                               laipsnis := laipsnis * 2;
                               inc (bitais);
                             end;
                       end;
                   zod := '';
                   while (tmp <> '') and (tmp[1] in raides) do
                     begin
                       zod := zod + tmp[1];
                       delete (tmp, 1, 1);
                     end;
                   if length (zod) > 1
                     then
                       begin
                         hash_pridek (sar, zod, kelintas);
                         il[kelintas] := length (zod);
                         inc (kelintas);
                         if kelintas = laipsnis
                           then
                             begin
                               laipsnis := laipsnis * 2;
                               inc (bitais);
                             end;
                       end;
                 end;
               paimk_bitu (s, 2);
               case skaicius (s) of
                 0: tmp := '';
                 1: tmp := ' ';
                 2: tmp := ',';
                 3: tmp := #13#10;
               end;
               blockwrite (fout, tmp[1], length (tmp));
               inc (jau, ilg);
               inc (jau, length (tmp));
             end;
          1: begin
               paimk_bitu (s, 6);
               sk := skaicius (s) + 1;
               tmp := '';
               for i := 1 to sk do
                 tmp := tmp + chr (tarpas);
               blockwrite (fout, tmp[1], sk);
               inc (jau, sk);
             end;
          2: begin
               paimk_bitu (s, 8);
               tmp := pagr[skaicius (s)];
               paimk_bitu (s, 2);
               case skaicius (s) of
                 1: tmp := tmp + chr (tarpas);
                 2: tmp := tmp + chr (kablelis);
                 3: tmp := tmp + #13#10;
               end;
               ilg := length (tmp);
               blockwrite (fout, tmp[1], ilg);
               inc (jau, ilg);
             end;
          3: begin
               paimk_bitu (s, bitais);
               nr := skaicius (s);
               ilg := il[nr];
               tmp_sar := sar[ilg];
               while tmp_sar^.nr <> nr do
                 tmp_sar := tmp_sar^.kitas;
               tmp := tmp_sar^.st;
               paimk_bitu (s, 2);
               case skaicius (s) of
                 1: tmp := tmp + chr (tarpas);
                 2: tmp := tmp + chr (kablelis);
                 3: tmp := tmp + #13#10;
               end;
               blockwrite (fout, tmp[1], length (tmp));
               inc (jau, length (tmp));
             end;
        end;
      end;
    close (fout);
  end;
begin
  new (buf);
  fillchar (buf^, sizeof (buf^), 0);
  hash_paruosk (ht);
  hash_paruosk (sar);
  hash_pagr (ht);
  write ('Encoding...');
  arch ('arch.txt', 'arch.e04');
  writeln (' done');
  hash_isvalyk (sar);
  hash_paruosk (sar);
  write ('Decoding...');
  dearch ('arch.e04', 'arch.d04');
  writeln (' done');
  hash_isvalyk (sar);
  hash_isvalyk (ht);
  dispose (buf);
end.{$A+,B-,D+,E+,F-,G-,I+,L+,N-,O-,P-,Q+,R+,S+,T-,V+,X+,Y+}
{$M 16384,0,655360}
{
1) u‘koduoja tarpus;
2) u‘koduoja standartinius Turbo Pascalio ‘od‘ius;
3) u‘koduoja visus besikartojancius ‘od‘ius;
4) u‘koduoja visus besikartojan‡ius simboli— kratinius, esan‡ius tarp ‘od‘i—;
5) vieno simbolio ne‘od‘ius koduoja kitaip (nekoduotoje informacijoje
atsiranda bitas, ‘ymintis ar toliau u‘koduota eilut‚ vieno simbolio ar
ilgesn‚);
}
program simple_RLE_plus_base_pascal_words_plus_all_repeating_words_plus_all_repeating_nonwords_plus_one_char_words_buisiness;
  const maxbuf = 65000;
        tarpas = 32;
        enter = 13;
        kablelis = 44;
        raides = ['0'..'9', 'A'..'Z', 'a'..'z', '_'];
  type buffer = array [1..maxbuf] of byte;
       ilgiai = array [0..maxbuf div 2] of byte;
  {$I zodziai.inc}
  var buf : ^buffer;
      il : ilgiai;
      sar : hash_lentele;
      b_in, b_out : longint;
  procedure arch (s1, s2 : string);
    var fin, fout : file;
        saug,       {saugo dar ne¨ra˛yt… ¨ byl… informacij…}
        isn : byte; {rodo, kiek bit— i˛ saugojimo bait— yra u‘imta}
        kelintas, laipsnis : word;
        nr : integer;
        i, bitais : byte;
        dabar, dydis : word;
        nekoduota : boolean;
        tmp : string;
    procedure issaugok (var saug, isn : byte);
    begin
      blockwrite (fout, saug, 1);
      saug := 0;
      isn := 0;
    end;
    procedure padek_bitu (s : string);
      var i : byte;
    begin
      for i := 1 to length (s) do
        begin
          saug := saug shl 1 + (ord (s[i]) - 48);
          inc (isn);
          if isn = 8
            then
              begin
                blockwrite (fout, saug, 1);
                saug := 0;
                isn := 0;
              end;
        end;
    end;
    procedure padek_eilute (s : string);
      var i, simb : byte;
    begin
      for i := 1 to length (s) do
        begin
          simb := ord (s[i]);
          saug := saug shl (8 - isn) + simb shr isn;
          blockwrite (fout, saug, 1);
          saug := byte (simb shl (8 - isn)) shr (8 - isn);
        end;
    end;
    procedure padek_skaiciu (sk : word; bitu : byte);
    begin
      while bitu + isn >= 8 do
        begin
          saug := saug shl (8 - isn) + byte (sk shr (bitu + isn - 8));
          blockwrite (fout, saug, 1);
          sk := sk shl (24 - bitu - isn) shr (24 - bitu - isn);
          bitu := bitu + isn - 8;
          saug := 0;
          isn := 0;
        end;
      saug := saug shl bitu + sk;
      isn := isn + bitu;
    end;
    procedure atlaisvink_tempa (var nekoduota : boolean; var tmp : string);
      var gale : byte;
    begin
      gale := 0;
      case ord (tmp[length (tmp)]) of
        tarpas: gale := tarpas;
        kablelis: gale := kablelis;
        enter: gale := enter;
      end;
      if gale > 0
        then delete (tmp, length (tmp), 1);
      padek_bitu ('00');
      if length (tmp) = 1
        then padek_bitu ('1')
        else
          begin
            padek_bitu ('0');
            padek_skaiciu (length (tmp), 7);
          end;
      padek_eilute (tmp);
      case gale of
        tarpas: padek_bitu ('01');
        kablelis: padek_bitu ('10');
        enter: padek_bitu ('11');
        else padek_bitu ('00');
      end;
      nekoduota := false;
      tmp := '';
    end;
    procedure koduok_tarpus (var nekoduota : boolean; var tmp : string);
      var kiek : byte;
    begin
      kiek := 0;
      inc (dabar);
      while (dabar < dydis) and (buf^[dabar] = tarpas) and (kiek < 31) do
        begin
          inc (dabar);
          inc (kiek);
        end;
      if kiek > 0
        then
          begin
            if tmp <> ''
              then
                begin
                  tmp := tmp + ' ';
                  atlaisvink_tempa (nekoduota, tmp);
                  dec (kiek);
                end;
            padek_bitu ('01');
            padek_skaiciu (kiek, 5);
          end
        else
          begin
            tmp := tmp + chr (tarpas);
            nekoduota := true;
          end;
    end;
    procedure koduok_zodi (var nekoduota : boolean; var tmp : string);
      var zod : string;
          ilg : byte;
          nr : integer;
    begin
      zod := '';
      while chr (buf^[dabar]) in raides do
        begin
          zod := zod + chr (buf^[dabar]);
          inc (dabar);
        end;
      ilg := length (zod);
      if ilg > 1
        then
          begin
            nr := hash_numeris (ht, zod);
            if nr <> -1
              then
                begin
                  if tmp <> ''
                    then atlaisvink_tempa (nekoduota, tmp);
                  padek_bitu ('10');
                  padek_skaiciu (nr, 8);
                  case buf^[dabar] of
                    tarpas: begin
                              padek_bitu ('01');
                              inc (dabar);
                            end;
                    kablelis: begin
                                padek_bitu ('10');
                                inc (dabar);
                              end;
                    enter: begin
                             padek_bitu ('11');
                             inc (dabar, 2);
                           end;
                    else padek_bitu ('00');
                  end;
                end
              else
                begin
                  nr := hash_numeris (sar, zod);
                  if nr <> -1
                    then
                      begin
                        if tmp <> ''
                          then atlaisvink_tempa (nekoduota, tmp);
                        padek_bitu ('11');
                        padek_skaiciu (nr, bitais);
                        case buf^[dabar] of
                          tarpas: begin
                                    padek_bitu ('01');
                                    inc (dabar);
                                  end;
                          kablelis: begin
                                      padek_bitu ('10');
                                      inc (dabar);
                                    end;
                          enter: begin
                                   padek_bitu ('11');
                                   inc (dabar, 2);
                                 end;
                          else padek_bitu ('00');
                        end;
                      end
                    else
                      begin
                        tmp := tmp + zod;
                        hash_pridek (sar, zod, kelintas);
                        inc (kelintas);
                        if kelintas = laipsnis
                          then
                            begin
                              laipsnis := laipsnis * 2;
                              inc (bitais);
                            end;
                        nekoduota := true;
                      end;
                end;
          end
        else
          begin
            tmp := tmp + zod;
            nekoduota := true;
          end;
    end;
    procedure koduok_nezodi (var nekoduota : boolean; var tmp : string);
      var nezod : string;
          nr : integer;
    begin
      nezod := '';
      while (dabar <= dydis) and not (chr (buf^[dabar]) in raides) and
            (buf^[dabar] <> enter) and ((buf^[dabar] <> tarpas){ or
            ((buf^[dabar] = tarpas) and (dabar < dydis) and
             (buf^[dabar + 1] <> tarpas))}) do
        begin
          nezod := nezod + chr (buf^[dabar]);
          inc (dabar);
        end;
      if (length (nezod) > 1)
        then
          begin
            nr := hash_numeris (sar, nezod);
            if nr <> -1
              then
                begin
                  if tmp <> ''
                    then atlaisvink_tempa (nekoduota, tmp);
                  padek_bitu ('11');
                  padek_skaiciu (nr, bitais);
                  case buf^[dabar] of
                    tarpas: begin
                              padek_bitu ('01');
                              inc (dabar);
                            end;
                    kablelis: begin
                                padek_bitu ('10');
                                inc (dabar);
                              end;
                    enter: begin
                             padek_bitu ('11');
                             inc (dabar, 2);
                           end;
                    else padek_bitu ('00');
                  end;
                end
              else
                begin
                  tmp := tmp + nezod;
                  hash_pridek (sar, nezod, kelintas);
                  inc (kelintas);
                  if kelintas = laipsnis
                    then
                      begin
                        laipsnis := laipsnis * 2;
                        inc (bitais);
                      end;
                  nekoduota := true;
                end;
          end
        else
          begin
            tmp := tmp + nezod;
            nekoduota := true;
          end;
    end;
  begin
    assign (fin, s1);
    reset (fin, 1);
    blockread (fin, buf^, maxbuf, dydis);
    close (fin);
    assign (fout, s2);
    rewrite (fout, 1);
    blockwrite (fout, dydis, sizeof (dydis));
    saug := 0;
    isn := 0;
    kelintas := 0;
    bitais := 1;
    laipsnis := 2;
    dabar := 1;
    tmp := '';
    while dabar <= dydis do
      begin
        nekoduota := true;
        while (dabar <= dydis) and nekoduota do
          begin
            while buf^[dabar] = tarpas do
              koduok_tarpus (nekoduota, tmp);
            koduok_zodi (nekoduota, tmp);
            koduok_nezodi (nekoduota, tmp);
            if buf^[dabar] = enter
              then
                begin
                  if tmp <> ''
                    then
                      begin
                        tmp := tmp + #13;
                        atlaisvink_tempa (nekoduota, tmp);
                      end
                    else tmp := #13#10;
                  inc (dabar, 2);
                end;
          end;
      end;
    if nekoduota and (tmp <> '')
      then atlaisvink_tempa (nekoduota, tmp);
    if isn > 0
      then
        begin
          saug := saug shl (8 - isn);
          blockwrite (fout, saug, 1);
        end;
    close (fout);
  end;
  procedure dearch (s1, s2 : string);
    var fin, fout : file;
        dabar, dydis, kiek, jau : word;
        s, inf, tmp, zod, nezod : string;
        i, ilg, sk : byte;
        kelintas, laipsnis: word;
        nr : integer;
        bitais : byte;
        tmp_sar : sarasas;
    procedure paimk_bitu (var s : string; kiek : byte);
      var i, baitas : byte;
          tmp : string;
    begin
      while kiek > length (inf) do
        begin
          baitas := buf^[dabar];
          inc (dabar);
          tmp := '';
          for i := 1 to 8 do
            begin
              tmp := chr (baitas and 1) + tmp;
              baitas := baitas shr 1;
            end;
          inf := inf + tmp;
        end;
      s := copy (inf, 1, kiek);
      delete (inf, 1, kiek);
    end;
    function skaicius (var s : string) : word;
      var i : byte;
          sk : word;
    begin
      sk := 0;
      for i := 1 to length (s) do
        sk := sk shl 1 + ord (s[i]);
      skaicius := sk;
    end;
  begin
    assign (fin, s1);
    reset (fin, 1);
    blockread (fin, dydis, sizeof (dydis));
    blockread (fin, buf^, maxbuf, kiek);
    close (fin);
    assign (fout, s2);
    rewrite (fout, 1);
    inf := '';
    dabar := 1;
    jau := 0;
    kelintas := 0;
    bitais := 1;
    laipsnis := 2;
    while jau < dydis do
      begin
        paimk_bitu (s, 2);
        case skaicius (s) of
          0: begin
               paimk_bitu (s, 1);
               if ord (s[1]) = 0
                 then
                   begin
                     paimk_bitu (s, 7);
                     ilg := skaicius (s);
                   end
                 else ilg := 1;
               tmp := '';
               for i := 1 to ilg do
                 begin
                   paimk_bitu (s, 8);
                   tmp := tmp + chr (skaicius (s));
                 end;
               paimk_bitu (s, 2);
               case skaicius (s) of
                 1: tmp := tmp + ' ';
                 2: tmp := tmp + ',';
                 3: tmp := tmp + #13#10;
               end;
               ilg := length (tmp);
               blockwrite (fout, tmp[1], ilg);
               while tmp <> '' do
                 begin
                   if tmp[1] = #13
                     then delete (tmp, 1, 2);
                   while (tmp <> '') and (tmp[1] = ' ') do
                     delete (tmp, 1, 1);
                   nezod := '';
                   while (tmp <> '') and not (tmp[1] in raides) and
                         (tmp[1] <> #13) and ((tmp[1] <> ' '){ or
                         ((tmp[1] = ' ') and ((length (tmp) = 1) or
                          ((length (tmp) > 1) and (tmp[2] <> ' '))))}) do
                     begin
                       nezod := nezod + tmp[1];
                       delete (tmp, 1, 1);
                     end;
                   if length (nezod) > 1
                     then
                       begin
                         hash_pridek (sar, nezod, kelintas);
                         il[kelintas] := length (nezod);
                         if il[kelintas] > max_ilg
                           then il[kelintas] := 1;
                         inc (kelintas);
                         if kelintas = laipsnis
                           then
                             begin
                               laipsnis := laipsnis * 2;
                               inc (bitais);
                             end;
                       end;
                   zod := '';
                   while (tmp <> '') and (tmp[1] in raides) do
                     begin
                       zod := zod + tmp[1];
                       delete (tmp, 1, 1);
                     end;
                   if length (zod) > 1
                     then
                       begin
                         hash_pridek (sar, zod, kelintas);
                         il[kelintas] := length (zod);
                         if il[kelintas] > max_ilg
                           then il[kelintas] := 1;
                         inc (kelintas);
                         if kelintas = laipsnis
                           then
                             begin
                               laipsnis := laipsnis * 2;
                               inc (bitais);
                             end;
                       end;
                 end;
               inc (jau, ilg);
               inc (jau, length (tmp));
             end;
          1: begin
               paimk_bitu (s, 5);
               sk := skaicius (s) + 1;
               tmp := '';
               for i := 1 to sk do
                 tmp := tmp + chr (tarpas);
               blockwrite (fout, tmp[1], sk);
               inc (jau, sk);
             end;
          2: begin
               paimk_bitu (s, 8);
               tmp := pagr[skaicius (s)];
               paimk_bitu (s, 2);
               case skaicius (s) of
                 1: tmp := tmp + chr (tarpas);
                 2: tmp := tmp + chr (kablelis);
                 3: tmp := tmp + #13#10;
               end;
               ilg := length (tmp);
               blockwrite (fout, tmp[1], ilg);
               inc (jau, ilg);
             end;
          3: begin
               paimk_bitu (s, bitais);
               nr := skaicius (s);
               ilg := il[nr];
               tmp_sar := sar[ilg];
               while tmp_sar^.nr <> nr do
                 tmp_sar := tmp_sar^.kitas;
               tmp := tmp_sar^.st;
               paimk_bitu (s, 2);
               case skaicius (s) of
                 1: tmp := tmp + chr (tarpas);
                 2: tmp := tmp + chr (kablelis);
                 3: tmp := tmp + #13#10;
               end;
               blockwrite (fout, tmp[1], length (tmp));
               inc (jau, length (tmp));
             end;
        end;
      end;
    close (fout);
  end;
begin
  new (buf);
  fillchar (buf^, sizeof (buf^), 0);
  hash_paruosk (ht);
  hash_paruosk (sar);
  hash_pagr (ht);
  write ('Encoding...');
  arch ('arch.txt', 'arch.e05');
  writeln (' done');
  hash_isvalyk (sar);
  hash_paruosk (sar);
  write ('Decoding...');
  dearch ('arch.e05', 'arch.d05');
  writeln (' done');
  hash_isvalyk (sar);
  hash_isvalyk (ht);
  dispose (buf);
end.{$A+,B-,D+,E+,F-,G-,I+,L+,N-,O-,P-,Q+,R+,S+,T-,V+,X+,Y+}
{$M 16384,0,655360}
{
1) u‘koduoja tarpus;
2) u‘koduoja standartinius Turbo Paskalio ‘od‘ius;
3) u‘koduoja visus besikartojan‡ius ‘od‘ius;
4) u‘koduoja visus besikartojan‡ius simboli— kratinius, esan‡ius tarp ‘od‘i—;
5) vieno simbolio ne‘od‘ius koduoja kitaip (nekoduotoje informacijoje
atsiranda bitas, ‘ymintis ar toliau u‘koduota eilut‚ vieno simbolio ar
ilgesn‚);
6) ne‘od‘io viduryje gali b–ti tarp—, bet du i˛ j— niekada neis i˛ eil‚s;
}
program simple_RLE_plus_base_pascal_words_plus_all_repeating_words_plus_all_repeating_nonwords_plus_one_char_words_buisiness;
  const maxbuf = 65000;
        tarpas = 32;
        enter = 13;
        kablelis = 44;
        raides = ['0'..'9', 'A'..'Z', 'a'..'z', '_'];
  type buffer = array [1..maxbuf] of byte;
       ilgiai = array [0..maxbuf div 2] of byte;
  {$I zodziai.inc}
  var buf : ^buffer;
      il : ilgiai;
      sar : hash_lentele;
      b_in, b_out : longint;
  procedure arch (s1, s2 : string);
    var fin, fout : file;
        saug,
        isn : byte;
        kelintas, laipsnis : word;
        nr : integer;
        i, bitais : byte;
        dabar, dydis : word;
        tmp : string;
    procedure issaugok (var saug, isn : byte);
    begin
      blockwrite (fout, saug, 1);
      saug := 0;
      isn := 0;
    end;
    procedure padek_bitu (s : string);
      var i : byte;
    begin
      for i := 1 to length (s) do
        begin
          saug := saug shl 1 + (ord (s[i]) - 48);
          inc (isn);
          if isn = 8
            then
              begin
                blockwrite (fout, saug, 1);
                saug := 0;
                isn := 0;
              end;
        end;
    end;
    procedure padek_eilute (s : string);
      var i, simb : byte;
    begin
      for i := 1 to length (s) do
        begin
          simb := ord (s[i]);
          saug := saug shl (8 - isn) + simb shr isn;
          blockwrite (fout, saug, 1);
          saug := byte (simb shl (8 - isn)) shr (8 - isn);
        end;
    end;
    procedure padek_skaiciu (sk : word; bitu : byte);
    begin
      while bitu + isn >= 8 do
        begin
          saug := saug shl (8 - isn) + byte (sk shr (bitu + isn - 8));
          blockwrite (fout, saug, 1);
          sk := sk shl (24 - bitu - isn) shr (24 - bitu - isn);
          bitu := bitu + isn - 8;
          saug := 0;
          isn := 0;
        end;
      saug := saug shl bitu + sk;
      isn := isn + bitu;
    end;
    procedure atlaisvink_tempa (var tmp : string);
      var gale : byte;
    begin
      gale := 0;
      case ord (tmp[length (tmp)]) of
        tarpas: gale := tarpas;
        kablelis: gale := kablelis;
        enter: gale := enter;
      end;
      if gale > 0
        then delete (tmp, length (tmp), 1);
      padek_bitu ('00');
      if length (tmp) = 1
        then padek_bitu ('1')
        else
          begin
            padek_bitu ('0');
            padek_skaiciu (length (tmp), 7);
          end;
      padek_eilute (tmp);
      case gale of
        tarpas: padek_bitu ('01');
        kablelis: padek_bitu ('10');
        enter: padek_bitu ('11');
        else padek_bitu ('00');
      end;
      tmp := '';
    end;
    procedure koduok_tarpus (var tmp : string);
      var kiek : byte;
    begin
      kiek := 0;
      inc (dabar);
      while (dabar < dydis) and (buf^[dabar] = tarpas) and (kiek < 31) do
        begin
          inc (dabar);
          inc (kiek);
        end;
      if kiek > 0
        then
          begin
            if tmp <> ''
              then
                begin
                  tmp := tmp + ' ';
                  atlaisvink_tempa (tmp);
                  dec (kiek);
                end;
            padek_bitu ('01');
            padek_skaiciu (kiek, 5);
          end
        else tmp := tmp + chr (tarpas);
    end;
    procedure koduok_zodi (var tmp : string);
      var zod : string;
          ilg : byte;
          nr : integer;
    begin
      zod := '';
      while chr (buf^[dabar]) in raides do
        begin
          zod := zod + chr (buf^[dabar]);
          inc (dabar);
        end;
      ilg := length (zod);
      if ilg > 1
        then
          begin
            nr := hash_numeris (ht, zod);
            if nr <> -1
              then
                begin
                  if tmp <> ''
                    then atlaisvink_tempa (tmp);
                  padek_bitu ('10');
                  padek_skaiciu (nr, 8);
                  case buf^[dabar] of
                    tarpas: begin
                              padek_bitu ('01');
                              inc (dabar);
                            end;
                    kablelis: begin
                                padek_bitu ('10');
                                inc (dabar);
                              end;
                    enter: begin
                             padek_bitu ('11');
                             inc (dabar, 2);
                           end;
                    else padek_bitu ('00');
                  end;
                end
              else
                begin
                  nr := hash_numeris (sar, zod);
                  if nr <> -1
                    then
                      begin
                        if tmp <> ''
                          then atlaisvink_tempa (tmp);
                        padek_bitu ('11');
                        padek_skaiciu (nr, bitais);
                        case buf^[dabar] of
                          tarpas: begin
                                    padek_bitu ('01');
                                    inc (dabar);
                                  end;
                          kablelis: begin
                                      padek_bitu ('10');
                                      inc (dabar);
                                    end;
                          enter: begin
                                   padek_bitu ('11');
                                   inc (dabar, 2);
                                 end;
                          else padek_bitu ('00');
                        end;
                      end
                    else
                      begin
                        tmp := tmp + zod;
                        hash_pridek (sar, zod, kelintas);
                        inc (kelintas);
                        if kelintas = laipsnis
                          then
                            begin
                              laipsnis := laipsnis * 2;
                              inc (bitais);
                            end;
                      end;
                end;
          end
        else tmp := tmp + zod;
    end;
    procedure koduok_nezodi (var tmp : string);
      var nezod : string;
          nr : integer;
    begin
      nezod := '';
      while (dabar <= dydis) and not (chr (buf^[dabar]) in raides) and
            (buf^[dabar] <> enter) and ((buf^[dabar] <> tarpas){ or
            ((buf^[dabar] = tarpas) and (dabar < dydis) and
             (buf^[dabar + 1] <> tarpas))}) do
        begin
          nezod := nezod + chr (buf^[dabar]);
          inc (dabar);
        end;
      if (length (nezod) > 1)
        then
          begin
            nr := hash_numeris (sar, nezod);
            if nr <> -1
              then
                begin
                  if tmp <> ''
                    then atlaisvink_tempa (tmp);
                  padek_bitu ('11');
                  padek_skaiciu (nr, bitais);
                  case buf^[dabar] of
                    tarpas: begin
                              padek_bitu ('01');
                              inc (dabar);
                            end;
                    kablelis: begin
                                padek_bitu ('10');
                                inc (dabar);
                              end;
                    enter: begin
                             padek_bitu ('11');
                             inc (dabar, 2);
                           end;
                    else padek_bitu ('00');
                  end;
                end
              else
                begin
                  tmp := tmp + nezod;
                  hash_pridek (sar, nezod, kelintas);
                  inc (kelintas);
                  if kelintas = laipsnis
                    then
                      begin
                        laipsnis := laipsnis * 2;
                        inc (bitais);
                      end;
                end;
          end
        else tmp := tmp + nezod;
    end;
  begin
    assign (fin, s1);
    reset (fin, 1);
    blockread (fin, buf^, maxbuf, dydis);
    close (fin);
    assign (fout, s2);
    rewrite (fout, 1);
    blockwrite (fout, dydis, sizeof (dydis));
    saug := 0;
    isn := 0;
    kelintas := 0;
    bitais := 1;
    laipsnis := 2;
    dabar := 1;
    tmp := '';
    while dabar <= dydis do
      begin
        while buf^[dabar] = tarpas do
          koduok_tarpus (tmp);
        koduok_zodi (tmp);
        koduok_nezodi (tmp);
        if buf^[dabar] = enter
          then
            begin
              tmp := tmp + #13;
              atlaisvink_tempa (tmp);
              inc (dabar, 2);
            end;
      end;
    if tmp <> ''
      then atlaisvink_tempa (tmp);
    if isn > 0
      then
        begin
          saug := saug shl (8 - isn);
          blockwrite (fout, saug, 1);
        end;
    close (fout);
  end;
  procedure dearch (s1, s2 : string);
    var fin, fout : file;
        dabar, dydis, kiek, jau : word;
        s, inf, tmp, zod, nezod : string;
        i, ilg, sk : byte;
        kelintas, laipsnis: word;
        nr : integer;
        bitais : byte;
        tmp_sar : sarasas;
    procedure paimk_bitu (var s : string; kiek : byte);
      var i, baitas : byte;
          tmp : string;
    begin
      while kiek > length (inf) do
        begin
          baitas := buf^[dabar];
          inc (dabar);
          tmp := '';
          for i := 1 to 8 do
            begin
              tmp := chr (baitas and 1) + tmp;
              baitas := baitas shr 1;
            end;
          inf := inf + tmp;
        end;
      s := copy (inf, 1, kiek);
      delete (inf, 1, kiek);
    end;
    function skaicius (var s : string) : word;
      var i : byte;
          sk : word;
    begin
      sk := 0;
      for i := 1 to length (s) do
        sk := sk shl 1 + ord (s[i]);
      skaicius := sk;
    end;
  begin
    assign (fin, s1);
    reset (fin, 1);
    blockread (fin, dydis, sizeof (dydis));
    blockread (fin, buf^, maxbuf, kiek);
    close (fin);
    assign (fout, s2);
    rewrite (fout, 1);
    inf := '';
    dabar := 1;
    jau := 0;
    kelintas := 0;
    bitais := 1;
    laipsnis := 2;
    while jau < dydis do
      begin
        paimk_bitu (s, 2);
        case skaicius (s) of
          0: begin
               paimk_bitu (s, 1);
               if ord (s[1]) = 0
                 then
                   begin
                     paimk_bitu (s, 7);
                     ilg := skaicius (s);
                   end
                 else ilg := 1;
               tmp := '';
               for i := 1 to ilg do
                 begin
                   paimk_bitu (s, 8);
                   tmp := tmp + chr (skaicius (s));
                 end;
               paimk_bitu (s, 2);
               case skaicius (s) of
                 1: tmp := tmp + ' ';
                 2: tmp := tmp + ',';
                 3: tmp := tmp + #13#10;
               end;
               ilg := length (tmp);
               blockwrite (fout, tmp[1], ilg);
               while tmp <> '' do
                 begin
                   if tmp[1] = #13
                     then delete (tmp, 1, 2);
                   while (tmp <> '') and (tmp[1] = ' ') do
                     delete (tmp, 1, 1);
                   nezod := '';
                   while (tmp <> '') and not (tmp[1] in raides) and
                         (tmp[1] <> #13) and ((tmp[1] <> ' '){ or
                         ((tmp[1] = ' ') and ((length (tmp) = 1) or
                          ((length (tmp) > 1) and (tmp[2] <> ' '))))}) do
                     begin
                       nezod := nezod + tmp[1];
                       delete (tmp, 1, 1);
                     end;
                   if length (nezod) > 1
                     then
                       begin
                         hash_pridek (sar, nezod, kelintas);
                         il[kelintas] := length (nezod);
                         if il[kelintas] > max_ilg
                           then il[kelintas] := 1;
                         inc (kelintas);
                         if kelintas = laipsnis
                           then
                             begin
                               laipsnis := laipsnis * 2;
                               inc (bitais);
                             end;
                       end;
                   zod := '';
                   while (tmp <> '') and (tmp[1] in raides) do
                     begin
                       zod := zod + tmp[1];
                       delete (tmp, 1, 1);
                     end;
                   if length (zod) > 1
                     then
                       begin
                         hash_pridek (sar, zod, kelintas);
                         il[kelintas] := length (zod);
                         if il[kelintas] > max_ilg
                           then il[kelintas] := 1;
                         inc (kelintas);
                         if kelintas = laipsnis
                           then
                             begin
                               laipsnis := laipsnis * 2;
                               inc (bitais);
                             end;
                       end;
                 end;
               inc (jau, ilg);
               inc (jau, length (tmp));
             end;
          1: begin
               paimk_bitu (s, 5);
               sk := skaicius (s) + 1;
               tmp := '';
               for i := 1 to sk do
                 tmp := tmp + chr (tarpas);
               blockwrite (fout, tmp[1], sk);
               inc (jau, sk);
             end;
          2: begin
               paimk_bitu (s, 8);
               tmp := pagr[skaicius (s)];
               paimk_bitu (s, 2);
               case skaicius (s) of
                 1: tmp := tmp + chr (tarpas);
                 2: tmp := tmp + chr (kablelis);
                 3: tmp := tmp + #13#10;
               end;
               ilg := length (tmp);
               blockwrite (fout, tmp[1], ilg);
               inc (jau, ilg);
             end;
          3: begin
               paimk_bitu (s, bitais);
               nr := skaicius (s);
               ilg := il[nr];
               tmp_sar := sar[ilg];
               while tmp_sar^.nr <> nr do
                 tmp_sar := tmp_sar^.kitas;
               tmp := tmp_sar^.st;
               paimk_bitu (s, 2);
               case skaicius (s) of
                 1: tmp := tmp + chr (tarpas);
                 2: tmp := tmp + chr (kablelis);
                 3: tmp := tmp + #13#10;
               end;
               blockwrite (fout, tmp[1], length (tmp));
               inc (jau, length (tmp));
             end;
        end;
      end;
    close (fout);
  end;
begin
  new (buf);
  fillchar (buf^, sizeof (buf^), 0);
  hash_paruosk (ht);
  hash_paruosk (sar);
  hash_pagr (ht);
  write ('Encoding...');
  arch ('arch.txt', 'arch.e06');
  writeln (' done');
  hash_isvalyk (sar);
  hash_paruosk (sar);
  write ('Decoding...');
  dearch ('arch.e06', 'arch.d06');
  writeln (' done');
  hash_isvalyk (sar);
  hash_isvalyk (ht);
  dispose (buf);
end.