Search code examples
prologtriangle

Prolog - get the greatest perimeter of triangles drawn with coordinates


The name and coordinates of a point in the plane can be given as points (A, X, Y).

Create a database by defining 10 points [such as point(a, 13, 47)] in accordance with this relationship in Prolog language.

Since three of these points will define a triangle, create rules that list these triangles.

Create a rule that prints on the screen by identifying the triangle with the largest perimeter among the triangles.

You have printed the program list with relations and rules, the list of triangles, and the triangle with the largest perimeter.

nokta(a, 3,1).
nokta(b, 6,2).
nokta(c, 7,1).
nokta(d, 9,1).
nokta(e, 6,3).
nokta(f, 4,3).
nokta(g, 9,3).
nokta(h, 13, 47).
nokta(i, 15, 49).  

istriangle(A, B, C) :-
  A > 0 ,
  B > 0 ,
  C > 0 ,
  A + B >= C ,
  A + C >= B ,
  B + C >= A .

calculate_the_perimeter_triangle(P1,P2,P3,AB,AC,BC,S) :-
  nokta(P1, X1, Y1),
  nokta(P2, X2, Y2),
  nokta(P3, X3, Y3),
  dif(P1, P2),
  dif(P2, P3),
  dif(P1, P3),
  \+ (X1 == X2, X2 == X3, X1 == X3),
  \+ (Y1 == Y2, Y2 == Y3, Y1 == Y3), 
  %IABI = √((x2 – x1) ²  + (y2 – y1) ² ) 
  AB is sqrt((X2-X1)^2 + (Y2-Y1)^2),
  %IACI = √((x3 – x1) ²  + (y3 – y1) ² ) 
  AC is sqrt((X3-X1)^2 + (Y3-Y1)^2),
  %IBCI = √((x3 – x2) ²  + (y3 – y2) ² )
  BC is sqrt((X3-X2)^2 + (Y3-Y2)^2),
  S is AB + AC + BC,
  AB > 0 ,
  AC > 0 ,
  BC > 0 .

calculate_perimeter_triangle(N1,N2,N3) :- 
  calculate_the_perimeter_triangle(X,Y,Z,N1,N2,N3,S),
  istriangle(N1,N2,N3),
  write(S - ' Bu koordinatlardan oluşan üçgen.'),
  nl,
  fail.

I got perimeter of triangles but I couldn't get perimeter of triangles


Solution

  • I might represent points like this, with a convenience predicate to give me a more concise notation, p( Name, X:Y ).

    point( p(N,P) ) :- point(N,P). 
    
    point( a ,   3 :  1 ).
    point( b ,   6 :  2 ).
    point( c ,   7 :  1 ).
    point( d ,   9 :  1 ).
    point( e ,   6 :  3 ).
    point( f ,   4 :  3 ).
    point( g ,   9 :  3 ).
    point( h ,  13 : 47 ).
    point( i ,  15 : 49 ).
    

    Then one can construct a triangle by simply drawing 3 distinct points from the database. We can do this by

    • getting each point
    • assembling all 3 into a list
    • using sort/2 to sort the list.

    sort/2 ensures that the list represents a set by removing duplicate elements, this ensure we don't make a triangle AAB for instance. That's just a line segment.

    sort/2 also, since we have the point's name as the first argument in out p/2 structure, orders the points in canonical order, so triangle ABC will be considered identical to triangle CBA.

    We then, using the built-in atom_chars/2 predicate, combine the three point names into a single atom to uniquely identify the triangle, and compute its perimeter.

    Finally we assembly it all into a t/5 structure of this form:

    t( Name, Point1, Point2, Point3, perimeter(Perimeter) )
    

    The code looks like this:

    triangle( t(N,Pa,Pb,Pc,perimeter(P)) ) :-
      point(P1) ,
      point(P2) ,
      point(P3) ,
      sort([P1,P2,P3],[p(A,Pa),p(B,Pb),p(C,Pc)]) , 
      atom_chars(N,[A,B,C]),
      perimeter(Pa,Pb,Pc,P) .
    

    Computing the perimeter is easy: we just compute the length of each leg of the triangle and sum them all:

    perimeter( P1, P2, P3, P ) :-
      distance(P1,P2,L1),
      distance(P2,P3,L2),
      distance(P3,P1,L3),
      P is L1+L2+L3
      .
    

    And computing the length of a line segment is easy: it's just the distance between two points on the Cartesian plane, using the distance formula derived from Pythagorean theorem:

    distance( X1:Y1, X2:Y2, D ) :- D is sqrt( (X2 - X1)^2 + (Y2 - Y1)^2 ).
    

    Now, each triangle carries with it all the information needed. We can collect the set of triangles that can be constructed from the set of points in the database using the built-in set_of/3 predicate: it both sorts and de-duplicates the list to be sorted:

    triangles( Ts ) :- setof( T , triangle(T), Ts ).
    

    The only task remaining is to identify the triangle with the longest perimeter. That's just a matter of recursively traversing the list, using a helper predicate that will track the triangle having the longest perimeter as we go:

    max_perimeter( [T|Ts] , Tmax ) :-
      max_perimeter( Ts, T, Tmax ).
    
    max_perimeter( []     , Tmax , Tmax ).
    max_perimeter( [T|Ts] , T0   , Tmax ) :-
      maxp(T,T0,T1),
      max_perimeter(Ts,T1,Tmax).
    
    maxp( T1, T2, T1 ) :- perimeter(T1,P1), perimeter(T2,P2), P1 >= P2, !.
    maxp( T1, T2, T2 ) :- perimeter(T1,P1), perimeter(T2,P2), P1 <  P2   .
    
    perimeter( t(_,_,_,_,perimeter(P)) , P ).
    

    We can then put it all together with a main/0 predicate to drive it all:

    point( p(N,P) ) :- point(N,P).
    
    point( a ,  3: 1  ).
    point( b ,  6: 2 ).
    point( c ,  7: 1 ).
    point( d ,  9: 1 ).
    point( e ,  6: 3 ).
    point( f ,  4: 3 ).
    point( g ,  9: 3 ).
    point( h , 13:47 ).
    point( i , 15:49 ).
    
    main :-
      triangles(Ts)      ,
      list_triangles(Ts) ,
      max_perimeter(Ts, Tmax),
      nl(),
      writeln(longest_perimeter) ,
      writeln(Tmax).
    
    triangles( Ts ) :- setof( T , triangle(T), Ts ) .
    
    triangle( t(N,Pa,Pb,Pc,perimeter(P)) ) :-
      point(P1) ,
      point(P2) ,
      point(P3) ,
      sort([P1,P2,P3],[p(A,Pa),p(B,Pb),p(C,Pc)]) , 
      atom_chars(N,[A,B,C]) ,
      perimeter(Pa,Pb,Pc,P)
      .
        
    perimeter( P1, P2, P3, P ) :-
      distance(P1,P2,L1),
      distance(P2,P3,L2),
      distance(P3,P1,L3),
      P is L1+L2+L3
      .
    
    distance( X1:Y1, X2:Y2, D ) :- D is sqrt( (X2 - X1)^2 + (Y2 - Y1)^2 ) 
     .
    
    list_triangles( [T|Ts] ) :-
       writeln(T),
       list_triangles(Ts).
    list_triangles( []     ).
    
    max_perimeter( [T|Ts] , Tmax ) :-
        max_perimeter( Ts, T, Tmax ).
    
    max_perimeter( []     , Tmax , Tmax ).
    max_perimeter( [T|Ts] , T0   , Tmax ) :-
        maxp(T,T0,T1),
        max_perimeter(Ts,T1,Tmax).
    
    maxp( T1, T2, T1 ) :- perimeter(T1,P1), perimeter(T2,P2), P1 >= P2, ! .
    maxp( T1, T2, T2 ) :- perimeter(T1,P1), perimeter(T2,P2), P1 <  P2   
     .
    
    perimeterf( t(_,_,_,_,perimeter(P)) , P ).
    

    Since you have a dataset of 9 points, there are 9 * 8 * 7, or 504 possible triangles. Running this shows that triangle with the longest perimeter is

    • Triangle: ADI
    • Perimeter: 103.85081399720322