{Scrieti o functie nerecursiva care returneaza adresa varfului listei unidirectionale.
 Transcrieti aceasta functie intr-o forma recursiva.}
Program Tema_2_4_Probl_1;
uses crt;
type AdresaCelula = ^Celula;
     Celula = record  {O celula din AdresaCelula}
       Info: String;  {Continutul celulei}
       Urm:  AdresaCelula;  {Adresa urmatoarei celule}
     end;

var L: AdresaCelula;   {L - baza listei}
    a, b: word; {Indicii elementelor care trebuiesc skimbate cu locul}

function Varf: AdresaCelula;
var R: AdresaCelula;
begin
 if L = nil then R := nil else {Lista este vida si nu are varf}
 begin
   R := L;
   while R^.Urm <> nil do R := R^.Urm; {Daca R^.Urm = nil, atunci R este adresa varfului}
 end;
 Varf := R;
end;

function Varf_rec(R: AdresaCelula): AdresaCelula;
begin
  if R^.Urm <> nil then R := Varf_rec(R^.Urm);
  Varf_rec := R;
end;

procedure Citeste;
var R, P: AdresaCelula;
begin
  new(L);
  P := L; {P indica ultima celula din lista}
  writeln('Scrie un text:');
  writeln;
  repeat
    new(R);           {Alocarea memoriei pentru o noua celula}
    readln(R^.Info);  {Popularea celulei cu informatie citita de la tastiera}
    if (R^.Info <> '') then begin
      P^.Urm := R;     {Atasam celula R la lista L1}
      P := R;          {R este ultima celula din L1}
    end else
    begin {P^.Info = ''}
       Dispose(R);          {Eliminam R}
       P^.Urm := nil;       {Marcam sfarsitul listei L1}
       {Prima celula din lista nu contine nimic, de aceea se elimina}
       R := L^.Urm;
       Dispose(L);
       L := R;
       Break;     {Lista a fost creata}
    end;
  until false;
end;

procedure Scrie;  {Afisarea listei}
var P: AdresaCelula;
begin
  P := L;  {Inceputul listei}
  while P <> nil do  {Pana nu se ajunge la sfarsitul listei}
    with P^ do begin
      Writeln(Info); {Afisarea informatiei din celula}
      P := Urm;      {Trecerea la urmatorul element}
    end;
end;

procedure Distruge;  {Distrugerea listei}
var P: AdresaCelula;
begin
  while L <> nil do
    with L^ do begin
      P := Urm;   {Salvarea adresei celulei urmatoare}
      Dispose(L); {Eliberarea memoriei ocupate de celula curenta}
      L := P;     {Trecerea la urmatoarea celula}
    end;
end;

begin
  clrscr;
  L := nil; {Baza listei}
  writeln;  writeln;
  Citeste;
  clrscr;
  writeln;  writeln;
  Scrie;
  writeln;  writeln;
  writeln('Varful este: ', Varf^.Info);
  writeln('Varful este (recursiv): ', Varf_rec(L)^.Info);

  Distruge;

  readkey;
end.