{ lihtne suurte naturaalarvude aritmeetika teek }
{ Ahto Truu }

{ naturaalarvu A esitame massiivina a[0..max], }
{ kus a[0] on üheliste number, a[1] kümneliste number jne }
{ see on üsna ebaefektiivne, aga väga mugav }

const max = 100; { suurte arvude pikkus }
type arv = array [0..max] of byte; { suurte arvud andmetüüp }

{ a := b }
procedure omista_v(var a : arv; b : integer);
var i : integer;
begin
   assert(b >= 0); { b peab olema naturaalarv }
   for i := 0 to max do begin
      a[i] := b mod 10;
      b := b div 10;
   end;
   assert(b = 0); { kui siin b > 0, siis on ületäitumine }
end;

{ a := b }
procedure omista_s(var a : arv; const b : arv);
var i : integer;
begin
   for i := 0 to max do begin
      a[i] := b[i];
   end;
end;

{ a := a + b }
procedure liida_v(var a : arv; b : integer);
var i : integer;
begin
   assert(b >= 0); { b peab olema naturaalarv }
   assert(b <= MAXINT - 9); { muidu tuleb vahesummas ületäitumine }
   for i := 0 to max do begin
      b := b + a[i];
      a[i] := b mod 10;
      b := b div 10;
   end;
   assert(b = 0); { kui siin b > 0, siis on ületäitumine }
end;

{ c := a + b }
procedure liida_s(var c : arv; const a, b : arv);
var i, x : integer;
begin
   x := 0; { ülekanne eelmisest järgust }
   for i := 0 to max do begin
      x := x + a[i] + b[i];
      c[i] := x mod 10;
      x := x div 10;
   end;
   assert(x = 0); { kui siin x > 0, siis on ületäitumine }
end;

{ a := a * b }
procedure korruta_v(var a : arv; b : integer);
var i, x : integer;
begin
   assert(b >= 0); { b peab olema naturaalarv }
   assert(b <= MAXINT div 10); { muidu tuleb vahesummas ületäitumine }
   x := 0; { ülekanne eelmisest järgust }
   for i := 0 to max do begin
      x := x + a[i] * b;
      a[i] := x mod 10;
      x := x div 10;
   end;
   assert(x = 0); { kui siin x > 0, siis on ületäitumine }
end;

{ c := a * b }
procedure korruta_s(var c : arv; const a, b : arv);
var ia, ib, j, x : integer;
begin
   omista_v(c, 0);
   for ia := 0 to max do begin
      for ib := 0 to max do begin
         j := ia + ib;
         x := a[ia] * b[ib];
         while x > 0 do begin
            assert(j <= max); { kui siin j > max, siis on ületäitumine }
            x := x + c[j];
            c[j] := x mod 10;
            x := x div 10;
            j := j + 1;
         end;
      end;
   end;
end;

{ a := a div b, tagastab jäägi }
function jaga_v(var a : arv; b : integer) : integer;
var i, x : integer;
begin
   assert(b > 0); { b peab olema naturaalarv ja ei tohi olla null }
   x := 0; { jääk eelmisest järgust }
   for i := max downto 0 do begin
      x := x * 10 + a[i];
      a[i] := x div b;
      assert(a[i] < 10); { see tuleb alati nii välja }
      x := x mod b;
   end;
   exit(x);
end;

{ jaga_s on olümpiaadil programmeerimiseks liiga vastik }
{ tuleb oma algoritm nii teha, et seda ei oleks vaja ;) }

{ tagastab -1, kui a1 < a2; 0, kui a1 = a2; +1, kui a1 > a2 }
function vordle_s(const a1, a2 : arv) : integer;
var i : integer;
begin
   for i := max downto 0 do begin
      if a1[i] < a2[i] then
         exit(-1);
      if a1[i] > a2[i] then
         exit(+1);
   end;
   exit(0);
end;

{ väljastab arvu a faili f }
procedure valjasta(var f : text; const a : arv);
var k, i : integer;
begin
   for k := max downto 0 do begin
      if a[k] > 0 then
         break;
   end;
   { väljastamist alustame esimesest mittenullist }
   for i := k downto 0 do begin
      write(f, a[i]);
   end;
end;

var a1, a2, a3 : arv; b : integer;
begin
   omista_v(a1, 9999);
   valjasta(output, a1); writeln(' 9999');
   omista_s(a2, a1);
   valjasta(output, a2); writeln(' 9999');
   liida_v(a1, 9);
   valjasta(output, a1); writeln(' 10008');
   liida_s(a3, a2, a1);
   valjasta(output, a3); writeln(' 20007');
   korruta_v(a1, 2);
   valjasta(output, a1); writeln(' 20016');
   korruta_s(a3, a2, a1);
   valjasta(output, a3); writeln(' 200139984');
   b := jaga_v(a3, 25);
   valjasta(output, a3); writeln(' 8005599');
   writeln(b, ' 9');
   writeln(vordle_s(a1, a2), ' 1');
   writeln(vordle_s(a1, a1), ' 0');
end.
