(* Programa que permite sumar numeros naturales de hasta cien dígitos de longitud *)
(* utilizando un array con tope *)
 
PROGRAM Aritnat(input,output);
 
CONST
    MaxDig = 100;  (* Constante que indica longitud maxima del numero *)
 
TYPE
   Digito = 0..9;  (* en cada celda del array se introducirán digitos del cero al nueve *)
   Natural = RECORD
                  digitos: ARRAY [1..MaxDig] OF Digito;
                  tope: 0..MaxDig;
             END;
VAR
  a, b, c:Natural;   (* a y b son los sumandos, c es el resultado de la suma *)
  suma, acarreo, i, digit:integer;  (* Variables para procesar los datos *)
  temp:integer;
 
 
BEGIN
 
    (* Lectura de los números a sumar *)
    writeln('Ingrese el primer numero:');
    
    readln(digit); (* Se ingresa el primer digito *)
    a.tope := 0;   (* Se inicializa el tope *)
    WHILE (digit IN [0..9]) AND ((a.tope < MaxDig) OR (a.tope = MaxDig)) DO
         BEGIN   (* Mientras el digito que se ingrese pertenesca al subrango 0..9 y mientras no se haya terminado el array *)
             a.tope := a.tope + 1;     (* Se incrementa en uno el tope del array *)
             a.digitos[a.tope] := digit;  (* Se almacena el digito en la celda correspondiente *)
             readln(digit)             (* Se lee el siguiente digito *)
         END;
 
 
    (* se solicita ingresar el segundo numero *)
 
    writeln('Ingrese el segundo numero:');
    readln(digit);   (* Se lee el primer digito *)
    b.tope := 0;     (* Se inicializa el tope *)
    WHILE (digit IN [0..9]) AND ((b.tope < MaxDig) OR (b.tope = MaxDig)) DO
         BEGIN     (* Mientras pertenesca al intervalo 0..9 y no se termine el array *)
             b.tope := b.tope + 1;  (* Se incrementa el tope *)
             b.digitos[b.tope] := digit;    (* Se almacena el digito en la celda correspondiente *)
             readln(digit)              (* Se lee el siguiente digito *)
         END;
 
 
    (* Si un array tiene mas digitos que otro, entonces al que tiene menos hay que agregarle ceros al principio *)
    (* Hasta que ambos tengan la misma longitud, de esa manera la suma se hará con mayor facilidad *)
 
    IF (a.tope > b.tope) THEN BEGIN
       FOR i := b.tope DOWNTO 1 DO BEGIN
           temp := b.digitos[i+(a.tope-b.tope)];
           b.digitos[i+(a.tope-b.tope)] := b.digitos[i];
           b.digitos[i] := temp;
           b.tope := b.tope + (a.tope - b.tope);
           END; (* FOR *)
       FOR i := 1 TO (a.tope - b.tope) DO
           b.digitos[i] := 0;
       END   (* if *)
       ELSE IF (b.tope > a.tope) THEN BEGIN
               FOR i := a.tope DOWNTO 1 DO BEGIN
                   temp := a.digitos[i+(b.tope-a.tope)];
                   a.digitos[i+(b.tope-a.tope)] := a.digitos[i];
                   a.digitos[i] := temp;
                   a.tope := a.tope + (b.tope-a.tope);
                   END;   (* FOR *)
               FOR i := 1 TO (b.tope - a.tope) DO 
                   a.digitos[i] := 0;
               END; (* ELSE IF *)
    
    c.tope := 0;
    FOR i := 1 TO (a.tope) DO BEGIN
        c.tope := c.tope + 1;
        c.digitos[i] := 0
        END;
 
    (* Ahora se le indicará a la máquina que sume los arreglos a y b como lo hacíamos en la escuela: digito a digito *)
    (* empezando por las unidades y de derecha a izquierda *)
    (* hay que considerar también el acarreo de las decenas, que por defecto, *)
    (* se inicializa en cero *)
 
    acarreo := 0;
    FOR i := (a.tope) DOWNTO 1 DO BEGIN
        suma := a.digitos[i] + b.digitos[i] + acarreo;
        IF (i = 1) AND (suma DIV 10 = 1) THEN BEGIN  (* caso excepcional: si al sumar el primer digito de a con el de b, el resultado es 10 o más, *)
           c.digitos[c.tope+1] := c.digitos[c.tope];  (* entonces, al array c se le agrega una cifra más al principio: la cifra del acarreo *)
           c.tope := c.tope + 1;
           c.digitos[2] := suma MOD 10;
           c.digitos[1] := suma DIV 10
        END (* IF *)
        ELSE BEGIN   (* sino, entonces sumamos cifra con cifra y almacenamos las unidades en la celda del array c, y las decenas que sobren en acarreo *)
                 c.digitos[i] := suma MOD 10;
                 acarreo := suma DIV 10
             END;  (* ELSE *)
        END;  (* FOR *)
 
    (* Para terminar, mostramos el resultado de la suma en pantalla *)
    FOR i := 1 TO (c.tope) DO
        write(c.digitos[i]);
    
    readln(i);
 
END.