PROBLEMA 13:          GHISEE
    DEADLINE:             Luni, 29 martie 1999
    TIMP DE IMPLEMENTARE: Dupa ce va vine ideea, 10 minute
    DOMENIU:              Liste (?). Interactiunea cu un modul al Onor. Comisii
    PUNCTAJ:              50 dexteri
    
    In Romania exista multe ghisee de reclamatii (oricum, nu mai mult de
    1,000,000), a caror treaba este de obicei sa plimbe oamenii de la un
    ghiseu la altul. Principiul de functionare al acestui sistem diabolic
    de ghisee este urmatorul: Un ghiseu poate fie sa rezolve problema
    celui care vine la el, fie sa il trimita la un alt ghiseu. Un ghiseu
    isi redirecteaza mereu reclamantii la acelasi ghiseu.
    
    Ghiseele au numere distincte, nenule, cuprinse intre 1 si
    2,000,000,000. Un om necajit merge la un prim ghiseu pentru a depune
    reclamatia "Pierdut speranta unei vieti mai bune. O declar nula". El
    intra astfel intr-un du-te-vino de la un ghiseu la altul. Omul doreste
    sa stie daca plimbarile sale au vreun sfarsit. Daca da, vrea sa afle
    numarul total de ghisee pe la care a fost plimbat, ca sa se poata
    lauda la prieteni. Daca nu (adica daca ghiseele incep sa il "paseze"
    ciclic de la unul la altul), el doreste sa stie cate ghisee se afla pe
    acest ciclu, pentru a anunta mass-media.
    
    Fie N numarul total de ghisee distincte pe la care poate fi plimbat
    omul. El nu cunoaste valoarea acestui numar N, dar mai are si alte
    treburi pe acasa si intentioneaza sa se lase pagubas dupa ce
    efectueaza 4*N plimbari de la un ghiseu la altul.
    
    Iata un exemplu: Fie 7 ghisee cu numerele 7, 11, 3, 9, 1, 8 si 13. Modul
    in care ele isi redirecteaza reclamantii este figurat mai jos:
    
         7 ----> 11 ----> 3 ----> 9 ----> 1                 8 ----> 13
                  ^                       |                 ^        |
                  ------------------------+                 ---------+
    
    In acest caz, N=5 (pentru ca omul poate fi plimbat pe la 5 ghisee,
    celelalte doua fiindu-i inaccesibile). El are la dispozitie 4*5=20 de
    deplasari de la un ghiseu la altul pentru a-si da seama ca ghiseele il
    plimba ciclic si ca in acest cerc vicios intra 4 ghisee (11, 3, 9, si 1).
    
    Programul vostru va trebui sa interactioneze cu modulul GHISEU.H,
    respectiv GHISEU.TPU, pe care vi-l furnizam noi, care va fi inclus in
    codul sursa cu comanda:
    
       Pascal: uses Ghiseu;
       C:      #include "ghiseu.h"
    
    Modulul furnizeaza doua functii:
    
    1) Pascal: function GimmeFirst:Longint;
       C:      long GimmeFirst(void)
    
    Aceasta functie indica numarul primului ghiseu la care trebuie sa
    mearga omul. Puteti apela functia de cate ori doriti.
    
    2) Pascal: function GimmeNext(X:Longint):Longint;
       C:      long GimmeNext(long X)
    
    Aceasta functie indica la ce ghiseu este trimis omul cand ajunge la
    ghiseul cu numarul X. Pentru exemplul de mai sus, GimmeNext(11) va
    intoarce intotdeauna 3. Daca functia intoarce valoarea 0, inseamna ca
    ghiseul X rezolva problema reclamantului. Aveti voie sa apelati
    aceasta functie de maxim 4*N ori; repetam ca valoarea lui N nu se da,
    ci trebuie dedusa.
    
    Programul vostru va trebui sa tipareasca pe ecran:
    a) Daca lantul de ghisee se inchide ciclic:
    Ma dau batut. Ciclul are P ghisee.
    
    b) Daca lantul de ghisee se termina la un moment dat:
    Am rezolvat reclamatia. Am vizitat Q ghisee.
    
    Pentru exemplul de mai sus, va trebui sa tipariti:
    Ma dau batut. Ciclul are 4 ghisee.
    
    Un test se considera picat in oricare din situatiile:
    1) Da un raspuns gresit;
    2) Apeleaza de mai mult de 4*N ori functia GimmeNext;
    3) Apeleaza functia GimmeNext trimitandu-i ca parametru un numar
       inexistent de ghiseu (pentru exemplul de mai sus, un numar din
       afara multimii  {1, 3, 7, 8, 9, 11, 13}).
    4) Depaseste un timp de rulare de 3 secunde. Se garanteaza ca 4*N
       apeluri ale functiei GimmeNext si (sa zicem) 10 apeluri ale
       functiei GimmeFirst nu depasesc o secunda.
    
    Incheiem cu doua exemple simple de module pe care le puteti folosi, care
    simuleaza urmatoarea structura de ghisee:
    
         1 ----> 2 ----> 3 ----> 4 ----> 5
                 ^                       |
                 ------------------------+
    
    ******************************* GHISEU.PAS *******************************
    unit ghiseu;
    interface
    
    function GimmeFirst:Longint;
    function GimmeNext(X:Longint):Longint;
    
    implementation
    var NCalls:Longint;
    
    function GimmeFirst:Longint;
    begin
      GimmeFirst:=1;
      NCalls:=0;
    end;
    
    function GimmeNext(X:Longint):Longint;
    begin
      if (X<1) or (X>5)
        then begin
               WriteLn('S-a ajuns in balarii!');
               Halt; { Terminare cu succes }
             end;
      Inc(NCalls);
      if (NCalls>20)
        then begin
               WriteLn('Prea multa alergatura!');
               Halt; { Terminare glorioasa }
             end;
      if X=5 then GimmeNext:=2
             else GimmeNext:=X+1;
    end;
    
    end.
    
    ******************************** GHISEU.H ********************************
    #include <stdio.h>
    #include <process.h>
    
    long NCalls=0;
    
    long GimmeFirst(void)
    { return 1; }
    
    long GimmeNext(long X)
    { if (X<1 || X>5) { puts("S-a ajuns in balarii!");
                        exit(0); } // Terminare cu succes
      if (++NCalls>20) { puts("Prea multa alergatura!");
                         exit(0); } // Terminare glorioasa
      return (X==5) ? 2 : X+1;
    }