/*
   Implementazione alternativa della coda di interi a lunghezza massima prefissata
   che si trova nei lucidi.
   In questa implementazione manteniamo il puntatore all'elemento presente da piu'
   tempo (indice 'front') ed il numero di elementi in coda ( variabile 'quanti').
   
   La coda e' vuota quando quanti vale 0, mentre e' piena quando quanti vale DIM.
   
   L'estrazione avviene dalla posizione front, dopodiche' front viene incrementato
   di uno modulo DIM (e quanti decrementato).
   
   Inserimento avviene nella posizione (front + quanti) modulo DIM,
   dopodiche' quanti viene incrementato (e front lasciato invariato).
   
   Con questa implementazione si riescono a memorizzare DIM interi
   e non DIM-1 come avviene nella soluzione presentata sui lucidi.
   
*/

#include <iostream>
using namespace std;

const int DIM = 5;

struct coda {
   int front, quanti;
   int queue[DIM];
};

// inizializzazione della coda
void inic(coda & cc){
   cc.front = cc.quanti = 0;
}

bool empty(const coda & cc){ // coda vuota?
   if (cc.quanti == 0) 
	   return true;
   return false;
}

bool full(const coda & cc){ //coda piena?
  if ( cc.quanti == DIM )
	  return true;
  return false;
}

bool insqueue(coda & cc, int s) // inserisce un elemento
{
   if (full(cc)) 
	  return false;
  
   int aux = (cc.front + cc.quanti) % DIM;
  
   cc.queue[aux] = s;
   cc.quanti++;
  
   return true;
}

bool esqueue(coda & cc, int & s) // estrae un elemento
{
    if (empty(cc)) 
		return false;	
    s = cc.queue[cc.front];
    cc.front = (cc.front + 1) % DIM;
	cc.quanti--;
    return true;
}

void stampa(const coda & cc) // stampa gli elementi
{
   cout<<endl;
   cout<<"Elementi presenti nella coda:"<<endl;
  
   for (int i = 0; i < cc.quanti; i++)
      cout << cc.queue[ (cc.front + i) % DIM] << endl;

   cout<<endl<<endl;
}

int main() {
	
   int num;
   coda qu;
   
   inic(qu);
   
   if (empty(qu)) 
	   cout << "La coda e' vuota" << endl<<endl;
   
   for (int i = 0; i < DIM; i++)
      if (insqueue(qu, i))
         cout << "Inserito l'elemento " << i << endl;
      else 
         cerr << "Inserimento fallito per coda piena" << endl;
	 
   if (full(qu)) 
      cout << "La coda e' piena" << endl;
  
   stampa(qu);
   
   for (int i = 0; i < DIM - 2; i++)
      if (esqueue(qu, num))
         cout << "Estratto l'elemento " << num << endl;
      else 
		 cout << "Estrazione fallita perche' la coda e' vuota " << endl;
	 
   stampa(qu);	 
   
   for (int i = 0; i < DIM; i++)
      if (insqueue(qu, i))
         cout << "Inserito l'elemento " << i << endl;
      else 
         cerr << "Inserimento fallito per coda piena" << endl;
	 
   stampa(qu);
  
   for (int i = 0; i < 2; i++)
      if (esqueue(qu, num))
         cout << "Estratto l'elemento " << num << endl;
      else 
         cout << "Coda vuota" << endl;
  
   stampa(qu);
  
   return 0;
   
}