/* File: operindu.c */
/* Time-stamp: "2001-03-29 18:09:41 calvanes" */
/* Scopo: esempio di funzioni ricorsive */

/* Realizza un'interfaccia utente per l'attivazione di un insieme di funzioni
   per eseguire le operazioni di somma, prodotto ed esponenziazione tra due
   interi nonnegativi.
   Le funzioni sono realizzate  sfruttando la definizione induttiva di tali
   operazioni, e senza usare gli operatori + e - del C e il valore 1,
   ma solo:
     - il valore 0,
     - il confronto tra due variabili di tipo intero
     - l'istruzione di assegnazione,
     - gli operatori di incremento ++ e decremento --
*/

/* - 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
*/


#include <stdio.h>


int somma(int x, int y)
  /* Calcola la somma tra due interi sfruttandone la definizione induttiva. */
{
  int prec;

  if (y == 0)
    return x;
  else {
    prec = somma(x, --y);
    return ++prec;
  }
}  /* somma */


int prodotto(int x, int y)
  /* Calcola il prodotto tra due interi sfruttandone la definizione induttiva.
   */
{
  if (y == 0)
    return 0;
  else
    return (somma(x, prodotto(x, --y)));
}  /* prodotto */


int esponente(int x, int y)
{
  /* Calcola l'elevamento a potenza tra due interi sfruttandone la definizione
     induttiva. */
  if (y == 0)
    return 1;
  else
    return (prodotto(x, esponente(x, --y)));
}  /* esponente */


int leggiIntero()
  /* Restituisce un intero letto da tastiera. */
{
  int i;

  printf("Immetti un intero ! ");
  scanf("%d%*[^\n]", &i);
  getchar();

  return i;
}  /* leggiIntero */


int main(void)
  /* OperazioniSuInteriRicorsive */
{
  int i, j;   /* interi su cui opera il programma */
  char ch;    /* carattere per la scelta */

  do {
    printf("\n*** IMMETTI UN CARATTERE A SCELTA FRA I SEGUENTI ***\n");
    printf("***** 1: leggi il primo intero\n");
    printf("***** 2: leggi il secondo intero\n");
    printf("***** 3: stampa il primo intero\n");
    printf("***** 4: stampa il secondo intero\n\n");
    printf("***** s: somma i due interi\n");
    printf("***** p: moltiplica i due interi\n");
    printf("***** e: eleva il primo intero al secondo\n\n");
    printf("***** Q: per terminare il programma\n\n");
    scanf("%c%*[^\n]", &ch);
    getchar();

    switch (ch) {
    case '1':
      i = leggiIntero();
      break;
    case '2':
      j = leggiIntero();
      break;
    case '3':
      printf("Primo intero  : %d\n", i);
      break;
    case '4':
      printf("Secondo intero: %d\n", j);
      break;
    case 's': case 'S':
      printf("Somma di %d e %d = %ld\n", i, j, somma(i, j));
      break;
    case 'p': case 'P':
      printf("Prodotto di %d e %d = %ld\n", i, j, prodotto(i, j));
      break;
    case 'e': case 'E':
      printf("%d elevato a %d = %ld\n", i, j, esponente(i, j));
      break;
    case 'q': case 'Q':
      printf("CIAO :-)\n");
      break;
    }
  } while (ch != 'Q' && ch != 'q');

  return 0;
}