Heronian triangles: Difference between revisions

Content added Content deleted
m (→‎{{header|Logtalk}}: Cleaned up some redundancy.)
(→‎{{header|Logtalk}}: Rewrote the test code to be more comprehensible, adding comments where needed. Changed representation from a tuple to a fact for performance reasons.)
Line 3,031: Line 3,031:
<syntaxhighlight lang="logtalk">
<syntaxhighlight lang="logtalk">
:- object(test_triangle).
:- object(test_triangle).

% define an alias for simpler output clauses
:- uses(logtalk, [print_message(information, heronian, Message) as print(Message)]).


:- public([start/0]).
:- public([start/0]).
Line 3,038: Line 3,041:
gather_primitive_heronians(Primitives),
gather_primitive_heronians(Primitives),
list::length(Primitives, L),
list::length(Primitives, L),
print('There are ~w primitive Heronian triangles with sides under 200.~n'+[L]),
logtalk::print_message(information, heronian,
'There are ~w primitive Heronian triangles with sides under 200.~n'+[L]),


list::sort(order_area, Primitives, AreaSorted),
list::sort(order_by_area, Primitives, AreaSorted),
list::take(10, AreaSorted, Area10),
list::take(10, AreaSorted, Area10),
print(@'The first ten found, ordered by area, are:\n'),
logtalk::print_message(information, heronian,
@'The first ten found, ordered by area, are:\n'),
display_each_element(Area10),
display_each_element(Area10),


list::sort(order_perimeter, Primitives, PerimeterSorted),
list::sort(order_by_perimeter, Primitives, PerimeterSorted),
list::take(10, PerimeterSorted, Perimeter10),
list::take(10, PerimeterSorted, Perimeter10),
print(@'The first ten found, ordered by perimeter, are:\n'),
logtalk::print_message(information, heronian,
@'The first ten found, ordered by perimeter, are:\n'),
display_each_element(Perimeter10),
display_each_element(Perimeter10),


bagof(Element, A^B^C^E^(list::member(Element, Primitives), Element = (A,B,C,210.0,E)), Area210),
bagof(Element, with_area(Element, Primitives, 210.0), Area210),
print(@'The list of those with an area of 210 is:\n'),
logtalk::print_message(information, heronian,
@'The list of those with an area of 210 is:\n'),
display_each_element(Area210).
display_each_element(Area210).


% localized helper predicates
% localized helper predicates


display_element((A,B,C,Area,Perimeter)) :-
with_area(E, P, N) :-
list::member(E, P),
E = t(_,_,_,N,_).

% display a single element in the provided format
display_single_element(t(A,B,C,Area,Perimeter)) :-
format(F),
format(F),
print(F+[A, B, C, Area, Perimeter]).
logtalk::print_message(information, heronian,
F+[A, B, C, Area, Perimeter]).


% display each element in a list of elements, printing a header first
display_each_element(L) :-
display_each_element(L) :-
logtalk::print_message(information, heronian, @' A B C Area Perimeter'),
print(@' A B C Area Perimeter'),
logtalk::print_message(information, heronian, @'=== === === ======= ========='),
print(@'=== === === ======= ========='),
loop::foreach(T, L, (display_element(T))),
loop::foreach(T, L, (display_single_element(T))),
logtalk::print_message(information, heronian, @'\n').
print(@'\n').


format('~|~` t~w~3+~` t~w~4+~` t~w~4+~` t~w~8+~` t~w~7+').
format('~|~` t~w~3+~` t~w~4+~` t~w~4+~` t~w~8+~` t~w~7+').


% collect all the primitive heronian triangles within the boundaries of the provided task
gather_primitive_heronians(Primitives) :-
gather_primitive_heronians(Primitives) :-
bagof(
bagof(
((A, B, C, Area, Perimeter)),
(t(A, B, C, Area, Perimeter)),
(
(
between(3, 200, A),
between(3, 200, A),
Line 3,087: Line 3,092:
).
).


% order triangles by area first, falling back to sides when areas are equal
order_area(=, T, T) :- !.
order_area(<, (_,_,_,Area1,_), (_,_,_,Area2,_)) :- Area1 < Area2, !.
order_by_area(=, T, T) :- !.
order_area(>, (_,_,_,Area1,_), (_,_,_,Area2,_)) :- Area1 > Area2, !.
order_by_area(<, t(_,_,_,Area1,_), t(_,_,_,Area2,_)) :- Area1 < Area2, !.
order_by_area(>, t(_,_,_,Area1,_), t(_,_,_,Area2,_)) :- Area1 > Area2, !.
order_area(O, T1, T2) :- order_sides(O, T1, T2).
order_by_area(O, T1, T2) :- order_by_sides(O, T1, T2).


% order triangles by perimeter first, falling back to sides when perimeters are equal
order_perimeter(=, T, T) :- !.
order_by_perimeter(=, T, T) :- !.
order_perimeter(<, (_,_,_,_,Perimeter1), (_,_,_,_,Perimeter2)) :- Perimeter1 < Perimeter2, !.
order_perimeter(>, (_,_,_,_,Perimeter1), (_,_,_,_,Perimeter2)) :- Perimeter1 > Perimeter2, !.
order_by_perimeter(<, t(_,_,_,_,Perimeter1), t(_,_,_,_,Perimeter2)) :- Perimeter1 < Perimeter2, !.
order_by_perimeter(>, t(_,_,_,_,Perimeter1), t(_,_,_,_,Perimeter2)) :- Perimeter1 > Perimeter2, !.
order_perimeter(O, T1, T2) :- order_sides(O, T1, T2).
order_by_perimeter(O, T1, T2) :- order_by_sides(O, T1, T2).


% order triangles by side A, then B, then C
order_sides(<, (A1,_,_,_,_), (A2,_,_,_,_)) :- A1 < A2, !.
order_sides(<, (_,B1,_,_,_), (_,B2,_,_,_)) :- B1 < B2, !.
order_by_sides(<, t(A1,_,_,_,_), t(A2,_,_,_,_)) :- A1 < A2, !.
order_sides(<, (_,_,C1,_,_), (_,_,C2,_,_)) :- C1 < C2, !.
order_by_sides(<, t(_,B1,_,_,_), t(_,B2,_,_,_)) :- B1 < B2, !.
order_by_sides(<, t(_,_,C1,_,_), t(_,_,C2,_,_)) :- C1 < C2, !.
order_sides(>, _, _).
order_by_sides(>, _, _).


:- end_object.
:- end_object.