program rotinas_de_deque;

Uses
  crt;

Const
  Tamanho=10;

Type
  Tipo_Dado = Integer;

  Tipo_Deque = Record
                Dado       : Array [1..Tamanho] of Tipo_Dado;
                Inicio,Fim : Integer;
              End;

{

  Rotinas de Manipulacao de Deques: DOUBLE ENDED QUEUES
  Deque com alocacao sequencial e estatica (circular)

procedure inicializa_deque    (var D:Tipo_Deque);
function  insere_inicio_deque (var D:Tipo_Deque; Dado:Tipo_Dado):Boolean;
function  insere_final_deque  (var D:Tipo_Deque; Dado:Tipo_Dado):Boolean;
function  retira_inicio_deque (var D:Tipo_Deque; var Dado:Tipo_Dado):Boolean;
function  retira_final_deque  (var D:Tipo_Deque; var Dado:Tipo_Dado):Boolean;
procedure exibe_deque         (D:Tipo_Deque);
function  acha_deque          (D:Tipo_Deque; Dado:Tipo_Dado; var Indice:Integer):Boolean;
function  consulta_deque      (D:Tipo_Deque; Indice:Integer; var Dado:Tipo_Dado):Boolean;
function  cheio_deque         (D:Tipo_Deque):Boolean;
function  vazio_deque         (D:Tipo_Deque):Boolean;
function  quantidade_deque    (D:Tipo_Deque):Integer;
procedure apaga_deque         (var D:Tipo_Deque);

}

procedure inicializa_deque (var D:Tipo_Deque);
begin
  D.inicio:=Tamanho;
  D.fim:=1;
end;

function insere_final_deque (var D:Tipo_Deque; Dado:Tipo_Dado):Boolean;
var
  prox:integer;
begin
  prox:=D.fim+1;

  if prox > Tamanho
  then prox:=1;

  if prox = D.inicio
  then insere_final_deque:=false
  else begin
         D.dado[D.fim]:=dado;
         D.fim:=prox;
         insere_final_deque:=true;
       end;
end;

function insere_inicio_deque (var D:Tipo_Deque; Dado:Tipo_Dado):Boolean;
var
  ant:integer;
begin
  ant:=D.inicio-1;

  if ant = 0
  then ant:=Tamanho;

  if ant = D.fim
  then insere_inicio_deque:=false
  else begin
         D.dado[D.inicio]:=dado;
         D.inicio:=ant;
         insere_inicio_deque:=true;
       end;
end;

function retira_inicio_deque (var D:Tipo_Deque; var Dado:Tipo_Dado):Boolean;
begin
  { Faca voce mesmo! }
end;

function retira_final_deque (var D:Tipo_Deque; var Dado:Tipo_Dado):Boolean;
Begin
  { Faca voce mesmo! }
End;

function cheio_deque (D:Tipo_Deque):Boolean;
var
  prox:integer;
  cheio:boolean;
begin
  prox:=D.fim+1;

  if prox > Tamanho
  then prox:=1;

  if prox = D.inicio
  then cheio:=true
  else cheio:=false;

  cheio_deque:=cheio;

end;

function vazio_deque (D:Tipo_Deque):Boolean;
var
  ant:integer;
  vazio:boolean;
begin
  ant:=D.fim-1;

  if ant = 0
  then ant:=Tamanho;

  if ant = D.inicio
  then vazio:=true
  else vazio:=false;

  vazio_deque:=vazio;

end;

function quantidade_deque (D:Tipo_Deque):Integer;
var
  cont:integer;
  total:integer;
begin
  total:=0;
  if not vazio_deque(D)
  then begin
         cont:=D.inicio+1;
         if cont > Tamanho then cont:=1;
         while cont <> D.fim
         do begin
              cont:=cont+1;
              total:=total+1;
              if cont > Tamanho
              then cont:=1;
            end;
       end;
  quantidade_deque:=total;
end;

procedure exibe_deque (D:Tipo_Deque);
var
  cont:integer;
begin
  writeln;
  writeln('Deque: ');
  writeln;
  if not vazio_deque(D)
  then begin

         cont:=D.inicio+1;
         if cont > Tamanho then cont:=1;

         while cont <> D.fim
         do begin
              writeln('Deque[',cont,']=',D.dado[cont]);
              cont:=cont+1;
              if cont > Tamanho
              then cont:=1;
            end;
       end
  else writeln('deque vazio...');
  writeln;
end;

function  acha_deque          (D:Tipo_Deque; Dado:Tipo_Dado; var Indice:Integer):Boolean;
Begin
  { Faca voce mesmo! }
End;

function  consulta_deque      (D:Tipo_Deque; Indice:Integer; var Dado:Tipo_Dado):Boolean;
Begin
  { Faca voce mesmo! }
End;

procedure apaga_deque         (var D:Tipo_Deque);
begin
  inicializa_deque(D);
end;

{ Programa Principal }

var
  Deque:Tipo_Deque;
  Valor:Integer;
  opcao:Integer;
  loop:Boolean;
begin
  inicializa_deque(Deque);

  loop:=true;
  while (loop)
  do begin
       clrscr;
       writeln('Estado do Deque: Inicio = ',Deque.inicio,' - Fim = ',Deque.fim);
       write  ('Deque Cheio: ',cheio_deque(Deque),' - ');
       write  ('Deque Vazio: ',vazio_deque(Deque),' - ');
       writeln('Quantidade : ',quantidade_deque(Deque));
       writeln;
       writeln('>> Rotinas de manipulacao de Deques <<');
       writeln;
       writeln('1 - Insere no Inicio');
       writeln('2 - Insere no Final');
       writeln('3 - Remove do Inicio');
       writeln('4 - Remove do Final');
       writeln('5 - Exibe  Deque');
       writeln('6 - Apaga  Deque');
       writeln('0 - FIM');
       writeln;
       write  ('Escolha uma opcao: ');
       readln (opcao);
       case opcao of
            1:begin
                write ('Valor: ');
                readln(Valor);
                if not insere_inicio_deque(Deque,Valor)
                then writeln('>>> Erro: Insere deque!')
                else writeln('>>> Valor inserido no inicio do deque!');
              end;
            2:begin
                write ('Valor: ');
                readln(Valor);
                if not insere_final_deque(Deque,Valor)
                then writeln('>>> Erro: Insere deque!')
                else writeln('>>> Valor inserido no inicio do deque!');
              end;
            3:begin
                writeln('Nao implementada...');
              end;
            4:begin
                writeln('Nao implementada...');
              end;
            5:begin
                exibe_deque(Deque);
              end;
            6:begin
                writeln('>> Apagando dados do deque...');
                apaga_deque(Deque);
                writeln('>> Deque re-inicializado!');
              end;
            0:loop:=false;
       else begin
              writeln('>> Opcao invalida!');
            end;
       end;

       if opcao <> 0
       then begin
              writeln('Pressione uma tecla para voltar ao menu...');
              readkey;
            end;

     end; { While loop }

  writeln;
  writeln('FIM');
  readln;

end.


