{Nicholas Tobey}

{4/08/10       }

{Contest #4    }

{Intermediate  }

{Enloe         }

{Potter        }

Program Pushpop;

 

uses

     crt,

     strings;

 

Type

     recMemLoc= ^rec;

     rec = Record

          data:string;

          next:recMemLoc;

     End;

 

var

     person:recMemLoc; {links to the first element of the list}

     current:recMemLoc;{                   }

     deepest:recMemLoc;{links to the penultimate element}

     prompt:string;    {the command entered}

     enter:string;     {the first part of the command entered}

     pvalue:integer;   {the parameter to be sent to functions}

     cvalue:string;

     code:integer;     {unused, for error messages}

     stack:boolean;    {true = stack, false = queue}

     continue:boolean;

     i:integer;

     depth:integer;

 

Procedure lread;

     Begin

          write(current^.data, ', ');

          current:= current^.next;

     End;

 

Procedure fullread(stack:boolean; num:integer);

     var

          dist:integer;

     Begin

          current:= person;

          writeln;

          if stack then

               Begin

                    for dist:= 1 to depth-num do

                         current:= current^.next;

                    {for dist:= depth-num to depth do}

                    while current <> NIL do

                         lread;

               End

          else

               Begin

                    for dist:= 1 to num do

                         lread;

               End;

          writeln;

     End;

 

Procedure deepfind;

     Begin

          if person^.next = nil then

               Begin

                    New(deepest);

                    deepest^.next:= person;

               End

          else deepest:= person;

          while deepest^.next^.next <> nil do deepest:= deepest^.next;

     End;

 

Procedure push(value:string);

     Begin

          if person = NIL then

               Begin

                    New(person);

                    person^.data:= value;

                    person^.next:= NIL;

                    current:= person;

                    New(deepest);

                    deepest^.next:= person;

               End

          else

               Begin

                    New(deepest^.next^.next);

                    deepest:= deepest^.next;

                    deepest^.next^.data:= value;

                    deepest^.next^.next:= NIL;

               End;

          depth:= depth+1;

     End;

 

Procedure pop(stack:boolean; num:integer);

     var

          hold:string;

          error:boolean;

          j:integer;

     Begin

          for j:= 1 to num do

               Begin

                    error:= false;

                    if person = NIL then

                         Begin

                              hold:= '';

                              error:= true;

                         End

                    else if stack and (person^.next <> nil) then

                         Begin

                              hold := deepest^.next^.data;

                              deepest^.next := NIL;

                              deepfind;

                         End

                    else

                         Begin

                              hold:= person^.data;

                              person:= person^.next;

                         End;

                    depth:= depth-1;

               End;

     End;

 

Procedure dup(num:integer);

     var

          j:integer;

     Begin

          current:= person;

          for j := 1 to num do

               Begin

                    push(current^.data);

                    current:= current^.next;

               End;

     End;

 

Procedure pin(value:string);

     var

          hold:recMemLoc;

     Begin

          New(hold);

          hold^.data:= value;

          hold^.next:= person;

          person:= hold;

          depth:= depth+1;

     End;

 

Procedure swap(num:integer);

     var

          upper:recMemLoc;

          lower:recMemLoc;

          j:integer;

          store:string;

     Begin

          upper:= person;

          lower:= person;

          for j:= 1 to depth-num do

               lower:= lower^.next;

          for j:= 1 to num do

               Begin

                    store:= lower^.data;

                    lower^.data:= upper^.data;

                    upper^.data:= store;

                    upper:= upper^.next;

                    lower:= lower^.next;

               End;

     End;

 

Procedure crc(stack:boolean; num:integer);

     var

          j:integer;

          hold:recMemLoc;

     Begin

          if stack then

               Begin

                    for j:= 1 to num do

                         Begin

                              new(hold);

                              hold^.data:= deepest^.next^.data;

                              hold^.next:= person;

                              person:= hold;

                              deepest^.next:= NIL;

                              deepfind;

                         End;

               End

          else

               Begin

                    for j:= 1 to num do

                         Begin

                              push(person^.data);

                              person:= person^.next;

                              depth:= depth - 1;

                         End;

               End;

     End;

 

Function cParse(var sr:string; comma:boolean):string;

     var

          bpoint:integer;

          hold:string;

          echar:string;

     Begin

          if comma then echar:= ',' else echar:= ' ';

          bpoint:= pos(echar, sr);

          if bpoint = 0 then

               Begin

                    hold:= sr;

                    sr:= '';

               End

          else

               Begin

                    hold:= copy(sr,1,bpoint-1);

                    delete(sr, 1,bpoint);

               End;

          cParse:= hold;

     End;

 

Function vParse(var sr:string; comma:boolean):integer;

     var

          bpoint:integer;

          hold:string;

          ihold:integer;

          echar:string;

     Begin

          if comma then echar:= ',' else echar:= ' ';

          bpoint:= pos(echar, sr);

          if bpoint = 0 then

               Begin

                    hold:= sr;

                    sr:= '';

               End

          else

               Begin

                    hold:= copy(sr,1,bpoint-1);

                    delete(sr, 1,bpoint);

               End;

          val(hold,ihold,code);

          vParse:= ihold;

     End;

 

Procedure initialize;

     Begin

          depth:= 0;

          person:= NIL;

          current:= person;

          deepest:= NIL;

          stack:= true;

          continue:= true;

          push('A');

          push('B');

          push('C');

          push('D');

          push('E');

     End;

 

Begin

     clrscr;

     for i:= 1 to 5 do

          Begin

               initialize;

               writeln;

               readln(prompt);

               repeat

                    enter:= cParse(prompt, false);

                         if enter = 'PSH' then push(cParse(prompt, true))

                    else if enter = 'POP' then pop(stack, vParse(prompt, true))

                    else if enter = 'SWH,'then stack:= not stack

                    else if enter = 'S,'  then stack:= true

                    else if enter = 'Q,'  then stack:= false

                    else if enter = 'DUP' then dup(vParse(prompt, true))

                    else if enter = 'PIN' then pin(cParse(prompt, true))

                    else if enter = 'SWP' then swap(vParse(prompt, true))

                    else if enter = 'CRC' then crc(stack, vParse(prompt, true))

                    else if enter = 'PRT' then fullread(stack, vParse(prompt, false));

               until prompt = '';

          End;

     readln;

End.