{ File: operindu.pas }

{ Scopo: esempio di funzioni ricorsive }

{
  - definizione induttiva di somma tra due interi nonnegativi

      somma(x,y) = x                    se y = 0
      somma(x,y) = 1 + (somma(x, y-1))  se y > 0

  - definizione induttiva di prodotto tra due interi nonnegativi

      prodotto(x,y) = 0                           se y = 0
      prodotto(x,y) = somma(x, prodotto(x, y-1))  se y > 0

  - definizione induttiva di elevamento a potenza tra due interi nonnegativi

      esponente(x,y) = 1                               se y = 0
      esponente(x,y) = prodotto(x, esponente(x, y-1))  se y > 0
}

program OperazioniSuInteriRicorsive;
{ Realizza un'interfaccia utente per l'attivazione di un insieme di funzioni
  per eseguire le operazioni di somma, prodotto ed elevamento a potenza tra due
  interi nonnegativi.
  Le funzioni sono realizzate  sfruttando la definizione induttiva di tali
  operazioni, e senza usare gli operatori + e - del PASCAL e il valore 1,
  ma solo:
    - il valore 0,
    - il confronto tra due variabili di tipo intero
    - l'istruzione di assegnazione,
    - le funzioni predefinite pred e succ
}

var
  i, j : integer;  { interi su cui opera il programma principale }
  ch   : char;     { carattere per la scelta }


  function Somma (x, y: integer): integer;
  { Calcola la somma tra due interi sfruttandone la definizione induttiva. }
  begin
    if y = 0 then
      Somma := x
    else
      Somma := succ(Somma(x, pred(y)))
  end; { Somma }


  function Prodotto (x, y: integer): integer;
  { Calcola il prodotto tra due interi sfruttandone la definizione induttiva. }
  begin
    if y = 0 then
      Prodotto := 0
    else
      Prodotto := Somma(x, Prodotto(x, pred(y)))
  end; { Prodotto }


  function Esponente (x, y: integer): integer;
  { Calcola l'elevamento a potenza tra due interi sfruttandone la definizione
    induttiva. }
  begin
    if y = 0 then
      Esponente := 1
    else
      Esponente := Prodotto(x, Esponente(x, pred(y)))
  end; { Esponente }


  procedure LeggiIntero (var int: integer);
  { Restituisce in i un intero letto da tastiera. }
  begin { LeggiIntero }
    write('Immetti un intero ! ');
    readln(int)
  end; { LeggiVettore }


begin  { OperazioniSuInteriRicorsive }
  repeat
    writeln;
    writeln('*** IMMETTI UN CARATTERE A SCELTA FRA I SEGUENTI ***');
    writeln('***** 1: leggi il primo intero');
    writeln('***** 2: leggi il secondo intero');
    writeln('***** 3: stampa il primo intero');
    writeln('***** 4: stampa il secondo intero');
    writeln;
    writeln('***** s: somma i due interi');
    writeln('***** p: moltiplica i due interi');
    writeln('***** e: eleva il primo intero al secondo');
    writeln;
    writeln('***** Q: per terminare il programma');
    writeln;
    readln(ch);  { ATTENZIONE: read NON va bene }

    case ch of
      '1'      : LeggiIntero(i);
      '2'      : LeggiIntero(j);
      '3'      : writeln('Primo intero  : ', i);
      '4'      : writeln('Secondo intero: ', j);
      's', 'S' : writeln('Somma di ', i, ' e ', j, ' = ', Somma(i,j));
      'p', 'P' : writeln('Prodotto di ', i, ' e ', j, ' = ', Prodotto(i,j));
      'e', 'E' : writeln(i, ' elevato a ', j, ' = ', Esponente(i,j));
      'q', 'Q' : writeln('CIAO :-)');
    end; { case }
  until (ch = 'Q') or (ch = 'q')
end. { OperazioniSuInteriRicorsive }