program ep95-303.pas;

{
Epreuve informatique de l'Ecole Polytechnique           95.303
--------------------------------------------------------------


On considère dans le plan euclidien un quadrilatère ABCD déformable dont
les quatre côtés ont des longueurs fixes :

	AB=a,  BC=b  CD=c   DA=d

Soient x et y les longueurs des deux diagonales : 	x=AC  y=BD

[FIGURE]

1/  Quelle condition nécessaire et suffisante les paramètres a, b, c et d
doivent-ils satisfaire pour que la construction de la figure soit possible ?

2/  Montrer qu'il existe une relation entre les six quantités a, b, c, d, x
et y.

3/ Les paramètres a, b, c et d étant supposés fixés, représenter la relation
qui lie x et y dans un repère cartésien Oxy et la tracer à l'aide de
l'ordinateur.
Commenter les différents cas de figure obtenus selon les valeurs des
paramètres.

(Application numérique suggérée : a=13, b=11, c=8, d=9)

4/ Chercher des cas de figure non triviaux tels que les six
longueurs  a, b, c, d, x et y s'expriment toutes par des nombres entiers.


:--------------------------------------------------------------:
:    Imprimer tous les résultats                               :
:     en indiquant chaque fois à quoi ils correspondent        :
:--------------------------------------------------------------:
                            -=-=-=-
 }


uses
    modubase, crt, printer;


const
     maxn=10;
type
  Myint=Longint;
  Myreal = Double;
  Distance1=myreal;
  Distance2=myreal;
  Distance3=myreal;
  Distance4=myreal;
  Distance6=myreal;
  Distance8=myreal;
  Distance9=myreal;
  Distance10=myreal;
  Angle=MyReal;

  matrice=array[1..maxn,1..maxn] of real;
  Points =record
      x,y:Distance1;
      t:string
  end;
var
   ch:char;
   n:integer;

   a,b,c,d,x,y1,y2,y1a,y2a,y:Distance1;
   c1,c2,c3:points;


procedure Comparer(s:string;x,y:Myreal);
var
   ecart:real;
const
    eps=0.01;
begin
     Ecris(s+' ');
     ecart:=abs(x-y)/max(eps,max(abs(x),abs(y)))
     if ecart<eps then
      Ecris(' OK.')
      else
       begin
             Ecris('! écart de ');
             EcrisEntier(round(ecart*100));
             Ecris('%');
       end;
end;

function distance(P1,P2:points):Distance1;
begin
     distance:=sqrt(sqr(p1.x-p2.x)+sqr(p1.y-p2.y));
end;

procedure NewPoint(var p:points;t:string;x,y:Distance1);
begin
    p.t:=t;
    p.x:=x;
    p.y:=y;
end;

procedure MontrePoint(p:points);
begin
    Croix(p.x,p.y);
    Ecris(p.t);
end;

procedure MontreSegment(p1,p2:points);
begin
     Deplace(p1.x,p1.y);
     Trace(p2.x,p2.y);
end;


procedure Calcule(a2,b2,c2,d2:Distance2;x:Distance1;VAR y1,y2:Distance1);
var
 x2:Distance2;
 x4:Distance4;
 q1:Distance4;
 q0:Distance6;
 disc:Distance8;
 u:Distance4;
 v:Distance2;
begin
     y1:=0;
     y2:=0;
     x2:=x*x;
     x4:=x2*x2;
     q1:=x4-(a2+b2+c2+d2)*x2+(a2-b2)*(d2-c2);


     q0:=(a2-d2)*(b2-c2)*x2+(a2-b2+c2-d2)*(a2*c2-b2*d2);
     disc:=q1*q1-4*x2*q0;
     if (disc>=0) and (x2<>0) then
        begin
             u:=sqrt(disc);
             v:=(-q1+u)/(2*x2);
             if v>0 then
                y1:=sqrt(v);
             v:=(-q1-u)/(2*x2);
             if v>0 then
                y2:=sqrt(v);
        end

end;

procedure Mouvement(a,b,c,d:Distance1);
var
   PA,PB,PC,PD,PC1,PD1:Points;
   a2,b2,c2,d2:Distance2;
   x,y,dx,ech,x1,y1:Distance1;
   possible,possible1:boolean;
   alpha,dalpha:angle;
   signe:integer;
   h,k:real;

   procedure calculer;
   var
      cosa,sina,cosb,sinb:real;
      p:Distance2;
      q:Distance3;
      r:Distance4;
      disc:Distance8;
      x2,y2:Distance2;
   begin


        possible:=false;
        cosa:=cos(alpha);
        sina:=sin(alpha);
        NewPoint(PC,'C',a-b*cosa,b*sina);

        x2:=a2+b2-2*a*b*cosa;

        p:=4*x2;
        q:=4*(a-b*cosa)*(c2-d2-x2);
        r:=sqr(x2+d2-c2)-4*b2*d2*(1-cosa*cosa);
        disc:=sqr(q)-4*p*r;
        if (disc>=0) and (abs(p)<>1E-6)then
          begin
               cosb:=(-q+signe*sqrt(disc))/(2*p*d);
               if abs(cosb)<=1 then
                  begin
                       possible:=true;
                       sinb:=sqrt(1-cosb*cosb);
                       y2:=a2+d2-2*a*d*cosb;
                       x1:=x;
                       y1:=y;
                       x:=sqrt(x2);
                       y:=sqrt(y2);
                       if possible1 then
                          begin
                              Couleur(Jaune);
                              Deplace(x1,y1);
                              Trace(x,y);
                          end;
                       NewPoint(PD,'D',  d*cosb,d*sinb);

   { At this step, there is an uncertainty about the sign of sinb }

                       if abs(distance(PC,PD)-c)>0.001 then
                          NewPoint(PD,'D',  d*cosb,-d*sinb);

       Deplace(k,h*0.90);Ecris('BC=');EcrisReel(distance(PB,PC));
                         Ecris(' CD=');EcrisReel(distance(PC,PD));
                         Ecris(' DA=');EcrisReel(distance(PA,PD));
        Deplace(k,h*0.85);Ecris('x=');EcrisReel(x);
                       Ecris(' y=');EcrisReel(y);
                  end;
           end;
   end;



begin
     a2:=a*a;
     b2:=b*b;
     c2:=c*c;
     d2:=d*d;
     ModeGraphique;
     ech:=max(max(max(a,b),c),d);


     Isofenetre(-ech,2*ech,-ech/2);
     Couleur(Vert);
     x_axe(0,0,1);
     Y_axe(0,0,1);
     Couleur(Brillant);
     h:=ech*1.5;
     k:=-1;
     Deplace(k,h*1.0);Ecris('Calculer abcd=');
         Ecrisreel(a);
         Ecrisreel(b);
         Ecrisreel(c);
         Ecrisreel(d);

     NewPoint(PA,'A',0,0);MontrePoint(PA);
     NewPoint(PB,'B',a,0);MontrePoint(PB);
     PC:=PB;PD:=PA;  {to avoid overflow}
     MontreSegment(PA,PB);
     possible:=false;
     alpha:=4*pi;
     dalpha:=0.01;
               repeat
           if alpha>2*pi then
              signe:=-1
           else
              signe:=1;
           possible1:=possible;
           PC1:=PC;
           PD1:=PD;
           alpha:=alpha-dalpha;
           Calculer;
           Couleur(-brillant);
           Croix(PC1.x,PC1.y);
           Croix(PC.x,PC.y);

           if possible1 then
            begin
                 MontreSegment(PA,PD1);
                 MontreSegment(PB,PC1);
                 MontreSegment(PC1,PD1);
            end;
           if possible then
            begin
                 MontreSegment(PA,PD);
                 MontreSegment(PB,PC);
                 MontreSegment(PC,PD);
            end;
     until alpha<0;
     Pause;



end;




procedure Question_1;
var
   a,b,c,d,x:Distance1;
   procedure Tester(a,b,c,d,x:Distance1);
   var
      y1,y2:Distance1;
   begin
           WriteLN('a=   b=    c=    d=      x=      y1=      y2=');
           Calcule(a*a,b*b,c*c,d*d,x,y1,y2);
           WriteLN(a:6:3,b:6:3,c:6:3,d:6:3,x:6:3,y1:8:3,y2:8:3);
   end;
begin
    Repeat

      Efface;
      WriteLN('   (1) Calcul pour a=1, b=4, c=3, d=3 , x=4  ');
      WriteLN('   (2) Calcul pour a=5, b=5, c=5, d=5 , x=6  ');
      WriteLN('   (3) Calcul pour a,b,c,d,x quelconques');
      WriteLN('                              ');
      Write('   Tapez votre Choix  :  ');
      Read(Ch);
          case ch of
               '1': Tester(1,4,3,3,4);
               '2': Tester(5,5,5,5,6);
               '3':
                begin
                     Write('Entrez a=');Read(a);
                     Write('Entrez b=');Read(b);
                     Write('Entrez c=');Read(c);
                     Write('Entrez d=');Read(d);
                     Write('Entrez x=');Read(x);
                     Tester(a,b,c,d,x);
                end;
               '0' : Halt
          end; {esac}
      Pause;
    until false;
end;



procedure Question_2;
begin
    Efface;
    WriteLN('     Equation XY²+UY+V=0                     ');
    WriteLN('     U=(X-A-B-C-D)X+(A-B)(D-C)                               ');
    WriteLN('     V=(Q-D)(B-C)X+(AC-BD)(A-B+C-D)            ');
    Pause;
    Repeat
      ModeTexte;
      Efface;
      WriteLN('   (1) Tracé pour a=1, b=1, c=1, d=1   ');
      WriteLN('   (2) Tracé pour a=4, b=3, c=2, d=1   ');
      WriteLN('   (3) Tracé pour a=4, b=2, c=2, d=1   ');
      WriteLN('   (4) Tracé pour a=4, b=4, c=2, d=1   ');
      WriteLN('   (5) Tracé pour a=4, b=1, c=4, d=2   ');
      WriteLN('   (6) Tracé pour a=4, b=1, c=4, d=4   ');
      WriteLN('   (7) Tracé pour a=2, b=3, c=4, d=5   ');
      WriteLN('   (8) Tracé pour a=13, b=12, c=11, d=8   ');
      WriteLN('   (9) Tracé pour a,b,c,d quelconques ');

      WriteLN('                              ');
      Write('   Tapez votre Choix  :  ');
      Read(Ch);
          case ch of
               '1':  Mouvement(1,1,1,1);
               '2':  Mouvement(4,3,2,1);
               '3':  Mouvement(4,2,2,1);
               '4':  Mouvement(4,4,2,1);
               '5':  Mouvement(4,1,4,2);
               '6':  Mouvement(4,1,4,4);
               '7':  Mouvement(2,3,4,5);
               '8':  Mouvement(13,12,11,8);
               '9':
                begin
                     Write('Entrez a=');Read(a);
                     Write('Entrez b=');Read(b);
                     Write('Entrez c=');Read(c);
                     Write('Entrez d=');Read(d);
                     Mouvement(a,b,c,d);
                end;
               '0' : Halt
          end;
     until false;
end;

Procedure Question_3;
const
 prt=false;
var
   a,b,c,d,x,y:Integer;
   a2,b2,c2,d2,x2,y2:integer;
   h:Double;
   df:text;

   function entier(x:Distance1):boolean;
   begin
        entier := abs(x-round(x))<0.000001;
   end;

   procedure try(y:Distance1);
   begin
      if entier(y) then
         if (y>0)then
            if not( (x<=abs(a-b))   or (x>=(a+b))
               or (x<=abs(c-d))   or (x>=(c+d))
               or (round(y)<=abs(a-d))   or (round(y)>=(a+d))
               or (round(y)<=abs(b-c))   or(round(y)>=(b+c) ))
            then
                begin
                     WriteLN;
                     Write(a:6,b:6,c:6,d:6,x:6,y:6:0);
                     WriteLN(df);
                      Write(df,'  ',a:6,b:6,c:6,d:6,x:6,y:6:0);
                end;
   end;
begin
     Efface;
     assign(df,'resultats.txt');
     rewrite(df);
     WriteLN('  AB=   BC=   CD=   DA=     AC=     BD=');
     WriteLN(df,'  AB=   BC=   CD=   DA=     AC=     BD=');
     for a:=3 to 1000 do
      begin
        write('.');
          for b:=1 to a do
               for c:=1 to a do
                 for d:=round(max(c,a-b-c+1)) to a do
                  begin
                    a2:=a*a;
                    b2:=b*b;
                    c2:=c*c;
                    d2:=d*d;
                    for x:=1 to (a+b+c+d) div 2 do
                      for y:=1 to (a+b+c+d) div 2 do
                          if not( (x<=abs(a-b))   or (x>=(a+b))
                          or (x<=abs(c-d))   or (x>=(c+d))
                          or (y<=abs(a-d))   or (y>=(a+d))
                          or (y<=abs(b-c))   or(y>=(b+c) ))
                          then
                          begin
                           x2:=x*x;
                           y2:=y*y;
                           h:=x2*y2*(x2+y2-a2-b2-c2-d2)
                             +(a2-d2)*(b2-c2)*x2
                             +(a2-b2)*(d2-c2)*y2
                             +(a2*c2-b2*d2)*(a2-b2+c2-d2);
                           if abs(h)<0.5 then
                              begin
                                 WriteLN;
                                 Write(a:6,b:6,c:6,d:6,x:6,y:6);
                                 WriteLN(df);
                                 Write(df,'  ',a:6,b:6,c:6,d:6,x:6,y:6);
                                 PAuse;
                              end;
                           end;
               end;
       end;
end;


Procedure Presentation;
begin;
      Efface;
      WriteLN(' ====== Diagonales d''un quadrilatère deformable=========');
      WriteLN('                                        ');
      WriteLN('                                        ');
      WriteLN('   (1) Calcul de y connaissant a,b,c,d,x');
      WriteLN('   (2) Deformation du quadrilatère  ');
      WriteLN('   (3) Recherche de valeurs entières ');

      WriteLN('                              ');
      Write('   Tapez votre Choix  :  ');
end;


begin
  Randomize;
  InitGraphique;
    repeat
           ModeTexte;
           Presentation;
          Read(Ch);
          case ch of
               '1':  Question_1;
               '2':  Question_2;
               '3':  Question_3;
               '0' : Halt
          end;
    until false;
end.
